diff --git a/TESTS/network/emac/main.cpp b/TESTS/network/emac/main.cpp index 49ee3cf909..8da3492421 100644 --- a/TESTS/network/emac/main.cpp +++ b/TESTS/network/emac/main.cpp @@ -35,7 +35,8 @@ !defined(TARGET_MTB_ADV_WISE_1530) && \ !defined(TARGET_MTB_USI_WM_BN_BM_22) && \ !defined(TARGET_MTB_MXCHIP_EMW3166) && \ - !defined(TARGET_MTB_UBLOX_ODIN_W2) + !defined(TARGET_MTB_UBLOX_ODIN_W2) && \ + !defined(TARGET_UNO_91H) #error [NOT_SUPPORTED] Wifi tests are not valid for the target #endif #endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp new file mode 100644 index 0000000000..0df8bb6fee --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp @@ -0,0 +1,217 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WiFiInterface.h" +#include "RdaWiFiInterface.h" +#include "rda5991h_wland.h" +#include "nsapi_types.h" +#include "wland_types.h" +#include "rda_sys_wrapper.h" + +nsapi_error_t RDAWiFiInterface::set_channel(uint8_t channel) +{ + int ret= 0; + init(); + + if (channel > 13) + return NSAPI_ERROR_PARAMETER; + + if (channel == 0) { + _channel = 0; + return NSAPI_ERROR_OK; + } + + ret = rda5981_set_channel(channel); + if (ret == 0) { + _channel = channel; + return NSAPI_ERROR_OK; + } else { + return NSAPI_ERROR_TIMEOUT; + } +} + +int8_t RDAWiFiInterface::get_rssi() +{ + return rda5981_get_rssi(); +} + +nsapi_error_t RDAWiFiInterface::init() +{ + if (!_interface) { + if (!_emac.power_up()) { + LWIP_DEBUGF(NETIF_DEBUG,"power up failed!\n"); + } + nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + } + return NSAPI_ERROR_OK; +} + +nsapi_error_t RDAWiFiInterface::set_credentials(const char *ssid, const char *pass, + nsapi_security_t security) +{ + if (ssid == 0 || strlen(ssid) == 0) { + return NSAPI_ERROR_PARAMETER; + } + if (security != NSAPI_SECURITY_NONE && (pass == 0 || strlen(pass) == 0)) { + return NSAPI_ERROR_PARAMETER; + } + if (strlen(ssid) > 32 || strlen(pass) > 63) { + return NSAPI_ERROR_PARAMETER; + } + memcpy((void*)_ssid, (void*)ssid, strlen(ssid)); + _ssid[strlen(ssid)] = '\0'; + memcpy((void*)_pass, (void*)pass, strlen(pass)); + _pass[strlen(pass)] = '\0'; + _security = security; + return NSAPI_ERROR_OK; +} + +nsapi_error_t RDAWiFiInterface::connect(const char *ssid, const char *pass, + nsapi_security_t security, uint8_t channel) +{ + rda_msg msg; + bool find = false; + int i = 0; + rda5981_scan_result bss; + int ret = 0; + + if (ssid == NULL || ssid[0] == 0) { + return NSAPI_ERROR_PARAMETER; + } + + init(); + + if(rda5981_check_scan_result_name(ssid) != 0) { + for (i = 0; i< 5; i++) { + rda5981_scan(NULL, 0, 0); + if(rda5981_check_scan_result_name(ssid) == 0) { + find = true; + break; + } + } + } else { + find = true; + } + + if (find == false) { + LWIP_DEBUGF(NETIF_DEBUG,"can not find the ap.\r\n"); + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + bss.channel = 15; + rda5981_get_scan_result_name(&bss, ssid); + if ((channel !=0) && (bss.channel != channel)) { + LWIP_DEBUGF(NETIF_DEBUG, "invalid channel\r\n"); + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + memcpy(gssid, ssid, strlen(ssid)); + if (pass[0] != 0) { + memcpy(gpass, pass, strlen(pass)); + } + memset(gbssid, 0, NSAPI_MAC_BYTES); + gssid[strlen(ssid)] = gpass[strlen(pass)] = '\0'; + + msg.type = WLAND_CONNECT; + rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); + ret = rda_sem_wait(wifi_auth_sem, 10000); + if (ret) { + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + ret = _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK, + _blocking); + + return ret; +} + + +nsapi_error_t RDAWiFiInterface::connect() +{ + return connect(_ssid, _pass, _security, _channel); +} + +nsapi_error_t RDAWiFiInterface::disconnect() +{ + rda_msg msg; + + if(sta_state < 2) { + return NSAPI_ERROR_NO_CONNECTION; + } + msg.type = WLAND_DISCONNECT; + rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); + if (_interface) { + return _interface->bringdown(); + } + + return NSAPI_ERROR_NO_CONNECTION; +} + +nsapi_size_or_error_t RDAWiFiInterface::scan(WiFiAccessPoint *res, nsapi_size_t count) +{ + int bss_num = 0, i; + rda5981_scan_result *bss; + nsapi_wifi_ap_t ap; + + init(); + + rda5981_scan(NULL, 0, 0); + bss_num = rda5981_get_scan_num(); + if (count != 0) { + bss_num = (bss_num < count) ? bss_num : count; + } + if (res) { + bss = (rda5981_scan_result *)malloc(bss_num * sizeof(rda5981_scan_result)); + rda5981_get_scan_result(bss, bss_num); + for (i=0; i +#ifdef __cplusplus +extern "C" { +#endif + +extern const unsigned int RDA_FW_INFO_ADDR; +extern const unsigned int RDA_UPGRADE_ADDR; + +/* + * function: start to wirte a partition. this func will erase given flash region + * @addr: partition start address, must be 4k alignment + * @img_len: length of image getted from OTA server, must be 4k alignment + * return: 0:success, else:fail + */ +int rda5981_write_partition_start(unsigned int addr, unsigned int img_len); + +/* + * function: write image to flash, without erase. + * the write region must be inside of the area given by func rda5981_write_partition_start + * the write region must be in order, otherwise the end function will return crc error. + * the maximum length could be write once time is 0x1000 + * @offset: offset from image inital position, must be 1k alignment + * @buf: data to be written + * @len: buffer len, max #0x1000, must be 1k alignment + * return: 0:success, else:fail + */ +int rda5981_write_partition(unsigned int offset, const unsigned char *buf, unsigned int len); + +/* + * function: end of writing partition + * return: 0:crc32 check success, else:fail + */ +int rda5981_write_partition_end(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_RDA5981_OTA_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h new file mode 100644 index 0000000000..0f0f4658e3 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RDA5981_SNIFFER_H_ +#define _RDA5981_SNIFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "wland_types.h" + +/* Enable filtering ACK frames (no support)*/ +//#define RDA_RX_FILTER_DROP_ACK BIT0 + +/* Enable filtering CTS frames (no support)*/ +//#define RDA_RX_FILTER_DROP_CTS BIT1 + +/* Enable filtering RTS frames (no support)*/ +//#define RDA_RX_FILTER_DROP_RTS BIT2 + +/* Enable filtering beacon frames */ +#define RDA_RX_FILTER_DROP_BEACON BIT3 + +/* Enable filtering ATIM frames (no support)*/ +//#define RDA_RX_FILTER_DROP_ATIM BIT4 + +/* Enable filtering CF_END frames (no support)*/ +//#define RDA_RX_FILTER_DROP_CF_END BIT5 + +/* Enable filtering QCF_POLL frames (no support)*/ +//#define RDA_RX_FILTER_DROP_QCF_POLL BIT6 + +/* Filter Management frames which are not directed to current STA */ +#define RDA_RX_FILTER_DROP_ND_MGMT BIT7 + +/* Filter BC/MC MGMT frames belonging to other BSS */ +#define RDA_RX_FILTER_DROP_BC_MC_MGMT_OTHER_BSS BIT8 + +/* Enable filtering of duplicate frames */ +#define RDA_RX_FILTER_DROP_DUPLICATE BIT9 + +/* Enable filtering of frames whose FCS has failed */ +#define RDA_RX_FILTER_DROP_FCS_FAILED BIT10 + +/* Enable filtering of De-authentication frame */ +#define RDA_RX_FILTER_DROP_DEAUTH BIT11 + +/* Filter BA frames which are not received as SIFS response (no support)*/ +//#define RDA_RX_FILTER_DROP_NSIFS_RESP_BA BIT12 + +/* Filter BA frames which are received as SIFS response (no support)*/ +//#define RDA_RX_FILTER_DROP_SIFS_RESP_BA BIT13 + +/* Filter frames which are received in secondary channel (20 MHz PPDU from Secondary channel) */ +#define RDA_RX_FILTER_DROP_SEC_CHANNEL BIT14 + +/* Filter BC/MC DATA frames belonging to other BSS */ +#define RDA_RX_FILTER_DROP_BC_MC_DATA_OTHER_BSS BIT15 + +/* Filter DATA frames not directed to this station */ +#define RDA_RX_FILTER_DROP_ND_DATA BIT16 + +/* Filter Control frames which are not directed to current STA (no support)*/ +//#define RDA_RX_FILTER_DROP_ND_CONTROL BIT17 + +/* Filter Beacon frames (in IBSS mode) which are not used for adoption because the timestamp field is lower than TSF timer */ +#define RDA_RX_FILTER_DROP_IBSS_BEACON BIT18 + +typedef int (*sniffer_handler_t)(unsigned short data_len, void *data); + +int rda5981_enable_sniffer(sniffer_handler_t handler); +int rda5981_disable_sniffer(void); +//don't use this in sniffer callback handler +int rda5981_disable_sniffer_nocallback(void); +///TODO: time is no use anymore +int rda5981_start_sniffer(unsigned char channel, unsigned char to_ds, + unsigned char from_ds, unsigned char mgm_frame, unsigned short time); +int rda5981_stop_sniffer(void); +int wland_sniffer_set_channel(unsigned char channel); +int rda5981_set_filter(unsigned char to_ds, unsigned char from_ds, unsigned int mgm_filter); +int rda5981_sniffer_enable_fcs(void);//for hiflying +#ifdef __cplusplus +} +#endif + +#endif /*_RDA5981_SNIFFER_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h new file mode 100644 index 0000000000..25ec00acbc --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h @@ -0,0 +1,658 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RDA5991H_WLAND_H_ +#define _RDA5991H_WLAND_H_ + +#include "sys_arch.h" +#include "wland_types.h" + +/* Mbed interface mac address + * if MBED_MAC_ADD_x are zero, interface uid sets mac address, + * otherwise MAC_ADD_x are used. + */ + +extern unsigned char user_mac[6];//not save in flash, need fill before wifi init every time +extern unsigned char gssid[32+1]; +extern unsigned char gpass[64+1]; +extern unsigned char gchannel; +extern unsigned char gbssid[6]; + +extern unsigned char gssid_ap[32+1]; +extern unsigned char gpass_ap[64+1]; +extern unsigned char gchannel_ap; +extern void *wland_msgQ; +extern void *wifi_auth_sem; + +extern u8 sta_state; + +typedef enum { + WLAND_CONNECT, + WLAND_RECONNECT, + WLAND_DISCONNECT, + WLAND_DISCONNECT_ERROR, + WLAND_STARTAP, + WLAND_STOPAP, + WLAND_ADD_AP_GTK, + WLAND_AP_EAPOL_3_OF_4, + WLAND_ADD_AP_PTK, + WLAND_STAJOINED, + WLAND_STAEXITED, + WLAND_STADEAUTH, + WLAND_MAC_CONNECTED, + WLAND_MAC_AP_CONNECTED, + WLAND_ADD_GTK, + WLAND_ADD_PTK, + WLAND_CON_FINISH, + WLAND_AUTO_RATE, + WLAND_ARP_OFFLOAD, + WLAND_SM_START, + WLAND_SM_STOP, + WLAND_WPS_CONNECT, + WLAND_WPS_START, + WLAND_WPS_DISCONNECT, +}WLAND_MSG; + +typedef enum { + MAIN_CONNECT, + MAIN_RECONNECT, + MAIN_DISCONNECT, + MAIN_STOP_AP, +}MAIN_MSG; + +typedef struct { + unsigned int type; + unsigned int arg1; + unsigned int arg2; + unsigned int arg3; +}rda_msg; + + +enum { + D_NONE_LEVEL = 0, + D_ERROR_LEVEL = 1, + D_INFO_LEVEL = 2, + D_DEBUG_LEVEL = 3, +}; + +#define WLAND_DBG_DUMP 0 +#define WPA_DBG_DUMP 0 +#define HUT_DBG_DUMP 0 +#define WLAND_DBG_LEVEL D_NONE_LEVEL +#define WPA_DBG_LEBEL D_NONE_LEVEL +#define WLANDLIB_DBG_LEVEL D_NONE_LEVEL + +#define ETH_ALEN 6 + +//encrypt type +#define ENCRYPT_NONE (0) +#define ENCRYPT_WPA_TKIP BIT0 +#define ENCRYPT_WPA_CCMP BIT1 +#define ENCRYPT_WPA2_TKIP BIT2 +#define ENCRYPT_WPA2_CCMP BIT3 +#define ENCRYPT_WEP BIT4 + +/* r91h driver data structure */ +typedef struct { + struct netif *netif_sta; + struct netif *netif_ap; + sys_thread_t wland_thread; + sys_thread_t maclib_thread; + sys_mbox_t maclib_mbox; + sys_mbox_t wland_mbox; +} rda_enetdata_t; + +__STATIC_INLINE int mac_is_valid(char* mac) +{ + return (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]); +} + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void wland_txip_data(void *data, unsigned int len, int mode); +extern void *wland_get_databuf(void); +extern void wland_sta_init(void); +extern void wland_reg_func(void); +extern void r91h_phy_task(void *data); +extern void wland_task(void *arg); +extern void rda_get_macaddr(u8_t *macaddr, int mode); +extern void rda5981_send_rawdata(char* data, unsigned int len); +extern int rda5981_send_nulldata(int power_save); +extern void rda5981_set_country_code(unsigned char country_code);// 0~china(1-14) 1~NA(1-11) 2~EU(1-13) +extern int rda5981_set_retrans_policy(unsigned char count); +extern int rda5981_set_channel(unsigned char channel); +/* default is 0, receive multicast packet, disable please set 1*/ +extern int rda5981_filter_multicast(unsigned char enable); +/* default is 0, 0 ~ no hidden, 1 ~ hidden zero len, 2 ~ hidden zero contents */ +extern void rda5981_set_AP_hidden_type(unsigned char mode); +extern void rda5981_set_AP_link_num(unsigned char num); +extern char* rda5981_get_ver(void); +extern int rda5981_enter_CE_MODE(unsigned char enable); +/* + * mode 0 - not 11n 1 - 11n + * + * -----------------11n(mode 1)(Mbps)----------------- + * rate HT20 HT40 + * GI(800ns) GI(400ns) GI(800ns) GI(400ns) + * 0 6.5 7.2 13.5 15 + * 1 13 14.2 27 30 + * 2 19.5 21.7 40.5 45 + * 3 26 28.9 54 60 + * 4 39 43.3 81 90 + * 5 52 57.8 108 120 + * 6 58.5 65 121.5 135 + * 7 65 72 135 150 + * + * --------------not 11n(mode 0)(Mbps)----------------- + * rate data rate rate data rate + * 0 autorate 9 9 + * 1 1 12 12 + * 2 2 18 18 + * 5 5.5 24 24 + * 11 11 36 36 + * 6 6 48 48 + * + */ +extern int rda5981_set_data_rate(unsigned char mode, unsigned char rate); +extern void rda5981_set_mode(unsigned char bgn_enable); +extern void rda5981_set_auth_timeout(unsigned char timeout_enable); +typedef struct { + char BSSID[ETH_ALEN]; + char SSID[32+1]; + signed char RSSI; + unsigned char SSID_len; + unsigned char channel; + unsigned char secure_type;//refer #define ENCRYPT_XXX + unsigned char wmm; + unsigned char *ie;//user program couldn't free(ie); + unsigned short capability; + unsigned int ie_length; +} rda5981_scan_result; + +typedef struct { + unsigned char mac[ETH_ALEN]; + unsigned int ip; +} rda5981_apsta_info; + +//scan one or all channel(if channel is 0) once +int rda5981_scan(const char *SSID, const unsigned char SSID_len, const unsigned char channel); +//0 passive mode, 1 active mode, scan time(unit is second) +int rda5981_scan_v2(const char *SSID, const unsigned char SSID_len, const unsigned char channel, const unsigned char mode, \ + const unsigned char scan_time); +int rda5981_get_scan_num(); +int rda5981_get_scan_result(rda5981_scan_result *buf, const unsigned char len); +int rda5981_get_scan_result_index(rda5981_scan_result *buf, const unsigned char index); +int rda5981_get_scan_result_name(rda5981_scan_result *buf, const char *name); +int rda5981_get_scan_result_bssid(rda5981_scan_result *buf, const unsigned char *bssid); +int rda5981_check_scan_result_name(const char *name); +int rda5981_check_scan_result(const char *ssid, const char *bssid, const unsigned channel); +int rda5981_check_scan_result_name_bssid(const unsigned char *name, const unsigned char *bssid); +int rda5981_del_scan_all_result(void); +void rda5981_set_expired_time(unsigned int expired_time); +int rda5981_get_joined_AP(rda5981_scan_result *bss); +s8 rda5981_get_rssi(); +void rda5981_set_main_queue(void* queue); + +void rda5981_set_sta_listen_interval(unsigned char interval); +void rda5981_set_sta_link_loss_time(unsigned char time); +unsigned int rda5981_get_ap_join_info(rda5981_apsta_info *buf, const unsigned char len); +void rda5981_set_AP_white_list(unsigned char flag, unsigned char *mac); +int wland_set_joined_sta_ip(char *mac, unsigned int ip); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_mac_addr(unsigned char *mac_addr); +int rda5981_flash_write_mac_addr(unsigned char *mac_addr); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_uart(void); +int rda5981_flash_read_uart(unsigned int *uart); +int rda5981_flash_write_uart(unsigned int *uart); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ip_addr(unsigned char *ip_addr, unsigned char *server_addr); +int rda5981_flash_write_ip_addr(unsigned char *ip_add, unsigned char *server_addr); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_dhcp_data(void); +int rda5981_flash_read_dhcp_data(unsigned int *enable, unsigned int *ip, unsigned int *msk, unsigned int *gw); +int rda5981_flash_write_dhcp_data(unsigned int enable, unsigned int ip, unsigned int msk, unsigned int gw); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel); +int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel); +int rda5981_flash_erase_ap_data(void); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, + unsigned int *dhcps, unsigned int *dhcpe); +int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, + unsigned int dhcps, unsigned int dhcpe); +int rda5981_flash_erase_ap_net_data(void); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_sta_data(char *ssid, char *passwd); +int rda5981_flash_write_sta_data(const char *ssid, const char *passwd); +int rda5981_flash_erase_sta_data(void); + + +/* + * read 3rd parter data length from flash + * return user data length + */ +int rda5981_flash_read_3rdparter_data_length(void); + +/* + * read 3rd parter data from flash + * @buf, buf to store user data + * @buf_len, length of buf + * return user data length + */ +int rda5981_flash_read_3rdparter_data(unsigned char *buf, unsigned int buf_len); + +/* + * write 3rd parter data from flash + * @buf, data to write + * @buf_len, length of buf. + * return 0:ok, else:fail + */ +int rda5981_flash_write_3rdparter_data(const unsigned char *buf, unsigned int buf_len); + +/* + * erase 3rd parter data from flash + * return 0:ok, else:fail + */ +int rda5981_flash_erase_3rdparter_data(void); + +/* + * set flash size + * @size, 1MB:0x100000, 2MB:0x200000, 4MB:0x400000. default size: 1MB + * return 0:ok, else:fail + */ +int rda5981_set_flash_size(const unsigned int size); + +/* + * set userdata location on flash + * @sys_data_addr, data to save system parameter, user can not operate this area directly. + * size:4KB. default location:0x180fb000 + * @user_data_addr, data to save user data. user can save own data in this area + * by @rda5981_flash_read_3rdparter_data + * and @rda5981_flash_write_3rdparter_data + * default location:0x180fc000 + * @user_data_len, user data length, default:4KB + * return 0:ok, else:fail + */ +int rda5981_set_user_data_addr(const unsigned int sys_data_addr, + const unsigned int user_data_addr, const unsigned int user_data_len); + +/* + * function: erase flash + * @addr: mast be 4k alignment + * @len: must be 4k alignment. (package 64KB erase and 4KB erase for different condition automatically) + * return: 0:success, else:fail + */ +int rda5981_erase_flash(unsigned int addr, unsigned int len); + +/* + * function: write flash + * @addr: mast be 256 alignment + * @buf: data to be written, best be 4 alignment + * @len: buffer len, mast be 4 alignment + * return: 0:success, else:fail + */ +int rda5981_write_flash(unsigned int addr, char *buf, unsigned int len); + +/* + * function: read flash to @buf + * @addr: best be 4 alignment + * @buf: best be 4 alignment + * @len: buffer len + * return: 0:success, else:fail + */ +int rda5981_read_flash(unsigned int addr, char *buf, unsigned int len); + +/* + * function: read user data + * @data: data to read + * @len: length of data in byte + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_read_user_data(unsigned char *data, unsigned short len, unsigned int flag); + +/* + * function: write user data + * @data: data to write + * @len: length of data in byte + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_write_user_data(unsigned char *data, unsigned short len, unsigned int flag); + +/* + * function: erase user data + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_erase_user_data(unsigned int flag); + +/* + * function: update tx power from efuse data, for reg 11F and 120 + * return: 0:success, else:fail + */ +int update_tx_power_from_efuse(void); + +/* + * function: update xtal calibration from efuse data, for reg DA + * return: 0:success, else:fail + */ +int update_xtal_cal_from_efuse(void); + +/* + * function: update mac addr from flash data + * return: 0:success, else:fail + */ +int update_mac_addr_from_efuse(void); + +/* + * function: update tx power from flash data, Deprecated version + * return: 0:success, else:fail + */ +int update_tx_power_from_flash(void); + +/* + * function: update tx power from flash data, for reg 8A + * return: 0:success, else:fail + */ +int update_tx_power_rf_from_flash(void); + +/* + * function: update tx power from flash data, for reg 11F and 120 + * return: 0:success, else:fail + */ +int update_tx_power_phy_from_flash(void); + +/* + * function: update xtal calibration from flash data + * return: 0:success, else:fail + */ +int update_xtal_cal_from_flash(void); + +/* + * function: update mac addr from flash data + * return: 0:success, else:fail + */ +int update_mac_addr_from_flash(void); + +/* + * function: write rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + * eg: 0x00DA:xtal calibration + */ +int wland_rf_write(unsigned short reg, unsigned short value); + +/* + * function: write rf reg + * @reg: rf reg data + * @value: rf reg value + * @len : value length + * return: 0:success, else:fail + * eg: 0x008A:tx power rf + */ +int wland_rf_write_all_channels(unsigned short reg, unsigned short *value, unsigned short len); + +/* + * function: read rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + */ +int wland_rf_read(unsigned short reg, unsigned short *value); + +/* + * function: read rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + * eg: 0x008A:tx power rf + */ +int wland_rf_read_all_channels(unsigned short reg, unsigned short *value); + +/* + * function: write phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_write(unsigned int reg, unsigned int value); + +/* + * function: write phy reg + * @reg: phy reg data + * @value: phy reg value + * @len : value length + * return: 0:success, else:fail + */ +int wland_phy_write_all_channels(unsigned int reg, unsigned int *value, unsigned short len); + +/* + * function: read phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_read(unsigned int reg, unsigned int *value); + +/* + * function: read phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_read_all_channels(unsigned int reg, unsigned int *value); + +/* efuse API start */ +/* Efuse CAN ONLY WRITE ONCE! DO NOT CALL THESE API IF YOU DO KNOW WHAT THEY MEANS!!! */ + +/* + * function: read all efuse + * @value: buffer to store efuse data, 28 bytes + * return: 0:success, else:fail + */ +int wland_read_efuse(unsigned char *value); + +/* + * function: read tx power from efuse + * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54). + * return: 0:success, else:fail + */ +int wland_read_tx_power_from_efuse(unsigned char *tx_power); + +/* + * function: read tx power from efuse + * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54) + * @len: must be 2 + * return: 0:success, else:fail + */ +int wland_write_tx_power_to_efuse(unsigned char *tx_power, unsigned char len); + +/* + * function: read xtal cal from efuse + * @xtal_cal: 1 byte, maximum 0x7F + * return: 0:success, else:fail + */ +int wland_read_xtal_cal_from_efuse(unsigned char *cal_val); + +/* + * function: write xtal cal to efuse + * @xtal_cal: 1 byte, maximum 0x7F + * @len : must be 1 + * return: 0:success, else:fail + */ +int wland_write_xtal_cal_to_efuse(unsigned char *xtal_cal, unsigned char len); + +/* + * function: write mac to efuse + * @xtal_cal: 6 bytes + * return: 0:success, else:fail + */ +int wland_read_mac_addr_from_efuse(unsigned char *mac_addr); + +/* + * function: write mac to efuse + * @xtal_cal: 6 bytes + * @len : must be 6 + * return: 0:success, else:fail + */ +int wland_write_mac_addr_to_efuse(unsigned char*mac_addr, unsigned char len); +/* efuse API end */ + +/* + * function: start rf test + * @argc: number of argv + * @argv: args for test, 6 elements for tx test, 4 elements for rx test + * @is_tx: 1 for tx test, 0 for rx test + * return: 0:success, else:fail + */ +int wland_start_rf_test(unsigned int argc, unsigned int *argv, unsigned int is_tx); + +/* + * function: stop rx test + * return: 0:success, else:fail + */ +int wland_stop_rx_test(void); + +/* + * function: get rf test result + * @result buffer to store rx result + * return: 0:success, else:fail + */ +int wland_get_rx_result(char *result); + +/* + * function: restart rx test, use last rx test args + * return: 0:success, else:fail + */ +int wland_restart_rx_test(void); + +/* + * function: stop tx test + * return: 0:success, else:fail + */ +int wland_stop_tx_test(void); + +/* + * function: restart tx test, use last tx test args + * return: 0:success, else:fail + */ +int wland_restart_tx_test(void); + +#define RDA5981_FIRMWARE_INFO_ADDR 0x18003000 +/* + * function: reboot to assigned addr (onece). + * reboot to rf test mode, not for OTA + * @firmware_info_addr: firmware info addr, depend on your flash layout + * @reboot_addr: reboot addr, 0x18001000-0x1840000 + * return: 0:success, else:fail + */ +int rda5981_reboot_to_addr(unsigned int firmware_info_addr, unsigned int reboot_addr); + +/* + * function: read reg and corresponding value related to test mode stored in flash + * @reg: reg to read + * @value: buffer to store value + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_read_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); + +/* + * function: write reg and corresponding value related to test mode stored in flash + * @reg: reg to write + * @value: buffer that stores value + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_write_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); + +/* + * function: erase reg and corresponding value related to test mode stored in flash + * @reg: reg to erase + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_erase_user_data_regs(unsigned char *reg, unsigned int flag); + +/* + * function: get flash Manufacturer ID + * @mid: + * return: 0:success, else:fail + */ +int rda5981_flash_get_mid(unsigned char *mid); + +/* + * function: get flash Device ID + * @did: + * return: 0:success, else:fail + */ +int rda5981_flash_get_did(unsigned char *did); + +/* + * function: get flash ID + * @mid: + * return: 0:success, else:fail + */ +int rda5981_flash_get_jdid(unsigned short *jdid); + +/* + * function: read mac reg + * @reg: mac reg data + * @value: mac reg value + * return: 0:success, else:fail + */ +int wland_mac_reg_read(unsigned short reg, unsigned int *value); + +/* + * function: write mac reg + * @reg: mac reg data + * @value: mac reg value + * return: 0:success, else:fail + */ +int wland_mac_reg_write(unsigned short reg, unsigned int value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h new file mode 100644 index 0000000000..25b80b5199 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h @@ -0,0 +1,216 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if 1 +#ifndef _RDA_SYS_WRAPPER_H_ +#define _RDA_SYS_WRAPPER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Alarm */ +/** + * @brief : get current time in units of micro second + * @param[in] : + * @param[out]: + * @return : return time value with uint32 type + */ +extern unsigned long rda_get_cur_time_ms(void); + +/** + * @brief : create an alarm with given function, return timer handle + * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) + * @param[out]: + * @return : return timer handle, a pointer to the timer structure, non-zero is valid + */ +extern void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode); +extern void * rda_alarm_create(void *func, unsigned int data); + +/** + * @brief : delete an alarm with given handle, then reset the handle + * @param[in] : *handle(pointer to the timer structure) + * @param[out]: **handle(address of the handle variable) + * @return : + */ +extern int rda_alarm_delete(void **handle); + +/** + * @brief : start an alarm, raise a function call after given timeout delay + * @param[in] : handle(pointer to the timer structure)/timeout(micro second) + * @param[out]: + * @return : + */ +extern int rda_alarm_start(void *handle, unsigned int timeout_ms); + +/** + * @brief : stop an alarm, will not raise a function call any more + * @param[in] : handle(pointer to the timer structure) + * @param[out]: + * @return : + */ +extern int rda_alarm_stop(void *handle); + + +/* Semaphore */ +/** + * @brief : create a semaphore + * @param[in] : name and initial valve of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern void* rda_sem_create(unsigned int count); + +/** + * @brief : wait a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_wait(void *sem, unsigned int millisec); + +/** + * @brief : release a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_release(void *sem); + +/** + * @brief : delete a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_delete(void *sem); + + +/* Queue */ +/** + * @brief : create a message queue + * @param[in] : size of message queue + * @param[out]: + * @return : return message queue id or NULL if error + */ +extern void* rda_msgQ_create(unsigned int queuesz); + +/** + * @brief : put a message to queue + * @param[in] : message queue id, message value and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_msg_put(void *msgQId, unsigned int msg, unsigned int millisec); + +/** + * @brief : get a message from queue + * @param[in] : message queue id, message value and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_msg_get(void *msgQId, unsigned int *value, unsigned int millisec); + +/* Mail */ +/** + * @brief : create a mail + * @param[in] : mail count/size + * @param[out]: + * @return : return mail handle + */ +void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize); + +/** + * @brief : get a msg from mail + * @param[in] : handler name of mail/mail/wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +int rda_mail_get(void *rdahandle, void *evt, unsigned int wait); + +/** + * @brief : put a msg to mail + * @param[in] : handler of mail/mail/wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ + +int rda_mail_put(void *rdahandle, void *evt, unsigned int wait); + +/* Mutex */ +/** + * @brief : create a mutex + * @param[in] : + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern void* rda_mutex_create(void); + +/** + * @brief : wait a mutex + * @param[in] : id of mutex and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_wait(void *rdamutex, unsigned int millisec); + +/** + * @brief : release a mutex + * @param[in] : id of mutex + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_realease(void *rdamutex); + +/** + * @brief : delete a mutex + * @param[in] : id of mutex + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_delete(void *rdamutex); + +/* Thread */ +/** + * @brief : creat a thread + * @param[in] : thread name/thread function/thread fuction argument/stacksize/thread priority + * @param[out]: + * @return : return thread id + */ +void* rda_thread_new(const char *pcName, void (*thread)(void *arg), void *arg, int stacksize, int priority); + +/** + * @brief : delete a thread + * @param[in] : thread id + * @param[out]: + * @return : return ERR or NO_ERR + */ +int rda_thread_delete(void* id); + +/** + * @brief : get current thread id + * @param[in] : + * @param[out]: + * @return : return thread id + */ +void* rda_thread_get_id(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _RDA_SYS_WRAPPER_H_ */ +#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h new file mode 100644 index 0000000000..ce418c023b --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_DBG_H_ +#define _WLAND_DBG_H_ +#include +#include "rda5991h_wland.h" +#include "wland_types.h" + +extern int wland_dbg_dump; +extern int wland_dbg_level; + +#define RDA_WLAND_DBG + +#ifdef RDA_WLAND_DBG +#define WLAND_DBG(level, fmt, ...) do {\ + int dbg_level = D_##level##_LEVEL;\ + if((dbg_level <= wland_dbg_level)){\ + printf("%s,"fmt, __func__, ##__VA_ARGS__);\ + } \ + } while (0) + +//if frmae_len is zero, get len from frame header +static inline void wland_dump_frame(const char* msg, u8 *data, u32 frame_len) +{ + + u32 len,i; + + if(wland_dbg_dump == 1) { + if(frame_len != 0) { + len = frame_len; + } else { + len = data[0] | ((data[1]&0x0f) << 8); + } + printf("%s : ",msg); + for(i=0; i= 4) { + wait_busy_down_4(); + } else { + wait_busy_down_2(); + } +} + +static void spi_write_reset(void) +{ + if (rda_ccfg_hwver() >= 4) { + spi_write_reset_4(); + } else { + spi_write_reset_2(); + } +} + +static void spi_wip_reset(void) +{ + if (rda_ccfg_hwver() >= 4) { + spi_wip_reset_4(); + } else { + spi_wip_reset_2(); + } +} + +static inline void spi_flash_enable_cache(void) +{ + unsigned int func = spi_flash_cfg_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_cfg_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void spi_flash_disable_cache(void) +{ + unsigned int func = spi_flash_disable_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_disable_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void spi_flash_flush_cache(void) +{ + unsigned int func = spi_flash_flush_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_flush_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void rda5981_spi_flash_erase_4KB_sector(u32 addr) +{ + unsigned int func = spi_flash_erase_4KB_sector_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_erase_4KB_sector_addr_4; + } + ((void(*)(u32))func)(addr); +} + +static inline void RDA5991H_ERASE_FLASH(void *addr, u32 len) +{ + unsigned int func = FLASH_ERASE_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_ERASE_FUN_ADDR_4; + } + ((void(*)(void *, u32))func)(addr, len); +} + +static inline void RDA5991H_WRITE_FLASH(u32 addr, u8 *data, u32 len) +{ + unsigned int func = FLASH_WRITE_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_WRITE_FUN_ADDR_4; + } + ((void(*)(u32, u8 *, u32))func)(addr, data, len); +} + +static inline void RDA5991H_READ_FLASH(u32 addr, u8 *buf, u32 len) +{ + unsigned int func = FLASH_READ_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_READ_FUN_ADDR_4; + } + ((void(*)(u32, u8 *, u32))func)(addr, buf, len); +} + +static inline void SPI_FLASH_READ_DATA_FOR_MBED(void *addr, void *buf, u32 len) +{ + unsigned int func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR_4; + } + ((void(*)(void *, void *, u32))func)(buf, addr, len); +} + +#endif /*_WLAND_FLASH_H_*/ + diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h new file mode 100644 index 0000000000..40ee40ee59 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_FLASH_WP_H_ +#define _WLAND_FLASH_WP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +extern void flash_wrtie_protect_all(); +extern void flash_wrtie_protect_none(); +extern void flash_wrtie_protect(unsigned int offset); +extern void rda5981_flash_init(); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h new file mode 100644 index 0000000000..57b9052871 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_OTA_H_ +#define _WLAND_OTA_H_ +#include "wland_types.h" +#include "rda_ccfg_api.h" + +extern u32 flash_size; + +#define CRC32_TABLE_ADDR 0xbb5c +#define CRC32_ADDR 0x8dff//u32 crc32(const u8 *p, size_t len) + +#define CRC32_TABLE_ADDR_4 0xbbd8 +#define CRC32_ADDR_4 0x8e33//u32 crc32(const u8 *p, size_t len) + +static inline unsigned int bootrom_crc32(unsigned char *p, unsigned int len) +{ + unsigned int func = CRC32_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = CRC32_ADDR_4; + } + return ((unsigned int(*)(unsigned char *, unsigned int))func)(p, len); +} + +#endif /*_WLAND_OTA_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h new file mode 100644 index 0000000000..6a9ebebc98 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_RF_H_ +#define _WLAND_RF_H_ + +#include "wland_types.h" + +#define WLAND_TXP_NUM 2 +#define WLAND_CHANNEL_NUM 14 +#define WLAND_TX_POWER_PHY_GN_REG 0x11F +#define WLAND_TX_POWER_PHY_B_REG 0x120 +#define WLAND_TX_POWER_RF_REG 0x8A +#define WLAND_XTAL_CAL_REG 0xDA + +#define MAKE_WORD16(lsb, msb) (((u16)(msb) << 8) & 0xFF00) | (lsb) +#define MAKE_WORD32(lsw, msw) (((u32)(msw) << 16) & 0xFFFF0000) | (lsw) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h new file mode 100644 index 0000000000..3cb0e7e9e6 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*****************************************************************************/ +/* */ +/* File Name : wland_types.h */ +/* */ +/* Description : This file contains all the data type definitions for */ +/* MAC implementation. */ +/* */ +/*****************************************************************************/ + +#ifndef WLAND_TYPES_H +#define WLAND_TYPES_H + +/*****************************************************************************/ +/* Constants Definitions */ +/*****************************************************************************/ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; + +typedef unsigned int size_t; + +/** Indicates Bit Value of BITx */ +#ifndef BIT +#define BIT(x) (1ul << (x)) + +/*****************************************************************************/ +/* Constant Definitions */ +/*****************************************************************************/ + +#define BIT0 (1ul << 0) +#define BIT1 (1ul << 1) +#define BIT2 (1ul << 2) +#define BIT3 (1ul << 3) +#define BIT4 (1ul << 4) +#define BIT5 (1ul << 5) +#define BIT6 (1ul << 6) +#define BIT7 (1ul << 7) +#define BIT8 (1ul << 8) +#define BIT9 (1ul << 9) +#define BIT10 (1ul << 10) +#define BIT11 (1ul << 11) +#define BIT12 (1ul << 12) +#define BIT13 (1ul << 13) +#define BIT14 (1ul << 14) +#define BIT15 (1ul << 15) +#define BIT16 (1ul << 16) +#define BIT17 (1ul << 17) +#define BIT18 (1ul << 18) +#define BIT19 (1ul << 19) +#define BIT20 (1ul << 20) +#define BIT21 (1ul << 21) +#define BIT22 (1ul << 22) +#define BIT23 (1ul << 23) +#define BIT24 (1ul << 24) +#define BIT25 (1ul << 25) +#define BIT26 (1ul << 26) +#define BIT27 (1ul << 27) +#define BIT28 (1ul << 28) +#define BIT29 (1ul << 29) +#define BIT30 (1ul << 30) +#define BIT31 (1ul << 31) +#endif + +#endif /* WLAND_TYPES_H */ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 0000000000..24e25298db --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, January 2019 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named “DEPENDENCIES” and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS 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. \ No newline at end of file diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md new file mode 100644 index 0000000000..5df1aa37df --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md @@ -0,0 +1,7 @@ +This directory tree contains binaries build from RDA SDK modified for Mbed OS and released under Permissive Binary License. + +libhal files in the subfolders are generated with toolchains: + +Arm Compiler 5 - version 5.06u6 +GNU Arm Embedded - version 6.3.1 +IAR EWARM - version 8.32.2.178 \ No newline at end of file diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar new file mode 100644 index 0000000000..3c5307cd77 Binary files /dev/null and b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a new file mode 100644 index 0000000000..58685c8562 Binary files /dev/null and b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a new file mode 100644 index 0000000000..a55e385361 Binary files /dev/null and b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c new file mode 100644 index 0000000000..bd31ff81d2 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c @@ -0,0 +1,275 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * @file : maclib_task.c + * @brief : WiFi MACLib task source file + * @version: V1.0 + * @date : 6. May 2017 + * + * @note + * + ******************************************************************************/ +#include +#include +#include + +#include "mbed_interface.h" +#include "cmsis_os.h" +#include "csl_mbed.h" +#include "maclib_task.h" +#include "rda5991h_wland.h" + +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +/** + * Macros + */ +#define MACLIB_TASK_DEBUG (0) + +/** + * Variables + */ +static int maclib_task_run = 0; +static sys_mbox_t maclib_mbox; +static int g_event_num = 0; +static int g_event_proc_done = 1; +static sys_sem_t g_maclib_sem_sleep; +static int g_maclib_sleep_flag = 0; + +extern maclib_func_t *maclib_func_p; + +extern void rda_critical_sec_start(void); +extern void rda_critical_sec_end(void); +extern void wland_set_sta_sleep(unsigned char is_sleep); + +#define MAX_MSG_POOL_NUM (64) +maclib_msg_t msg_str_pool[MAX_MSG_POOL_NUM]; +int msg_str_pool_inited = 0; + +void init_msg_str_pool(void) +{ + int idx; + for(idx = 0; idx < MAX_MSG_POOL_NUM; idx++) { + msg_str_pool[idx].is_free = 1; + } +} + +maclib_msg_t *alloc_msg_str(void) +{ + int idx; + maclib_msg_t *ret = NULL; + rda_critical_sec_start(); + if (0 == msg_str_pool_inited) { + init_msg_str_pool(); + msg_str_pool_inited = 1; + } + rda_critical_sec_end(); + for (idx = 0; idx < MAX_MSG_POOL_NUM; idx++) { + rda_critical_sec_start(); + ret = &msg_str_pool[idx]; + if (1 == ret->is_free) { + ret->is_free = 0; + rda_critical_sec_end(); + break; + } + rda_critical_sec_end(); + } + return ret; +} + +void free_msg_str(maclib_msg_t *p_msg) +{ + rda_critical_sec_start(); + p_msg->is_free = 1; + rda_critical_sec_end(); +} + +/** + * Functions + */ +/* maybe called in isr, should not use "printf", "malloc" */ +void mbed_event_handle_cb(unsigned int event) +{ + MACLIB_EVENT_HANDLE_T type = (MACLIB_EVENT_HANDLE_T)event; + if ((maclib_task_run == 0) && (MACLIB_EVENT_CLEANUP != type)) { + mbed_error_printf("evntHndlCb_nulldata\r\n"); + return; + } + switch(type) { + case MACLIB_EVENT_PEND: + rda_critical_sec_start(); + g_event_num++; + if((1 == g_event_num) && (1 == g_event_proc_done)) { + maclib_msg_t *msg; +#if MACLIB_TASK_DEBUG + mbed_error_printf("#1-1,%d(%08X)\r\n", g_event_num, __get_xPSR()); +#endif + msg = alloc_msg_str(); + if(NULL == msg) { + mbed_error_printf("malloc err\r\n"); + return; + } + msg->type = MACLIB_MSG_EVNT_HNDL; + msg->msg = NULL; + sys_mbox_trypost(&(maclib_mbox), msg); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#1-2\r\n"); +#endif + } + rda_critical_sec_end(); + break; + case MACLIB_EVENT_PROCESS: +#if 1 + rda_critical_sec_start(); + g_event_num--; + if(0 > g_event_num) { + mbed_error_printf("event handle err\r\n"); + g_event_num = 0; + } + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#3,%d\r\n",g_event_num); +#endif +#endif + break; + case MACLIB_EVENT_CLEANUP: +#if MACLIB_TASK_DEBUG + mbed_error_printf("event cleanup\r\n"); +#endif + rda_critical_sec_start(); + g_event_num = 0; + rda_critical_sec_end(); + break; + default: + break; + } +} + +void mbed_mltask_sleep_cb(void) +{ + g_maclib_sleep_flag = 1; + sys_arch_sem_wait(&g_maclib_sem_sleep, 0); +} + +void mbed_mltask_wakeup_cb(void) +{ + rda_critical_sec_start(); + if (1 == g_maclib_sleep_flag) { + g_maclib_sleep_flag = 0; + sys_sem_signal(&g_maclib_sem_sleep); + } + rda_critical_sec_end(); +} + +void maclib_check_status(void) +{ + rda_critical_sec_start(); + if (1 == g_maclib_sleep_flag) { + if(*((unsigned int *)0x40020580U) & (0x01UL << 2)) { + mbed_mltask_wakeup_cb(); + } + } + rda_critical_sec_end(); +} + +int maclib_is_sleep_allowed(void) +{ + return g_maclib_sleep_flag; +} + +void maclib_task(void *pvParameters) +{ + int ret; +#if 0 + sleep_entry_t maclib_sleep_entry = { + wland_set_sta_sleep, + maclib_is_sleep_allowed, + maclib_check_status + }; +#endif + sys_sem_new(&g_maclib_sem_sleep, 0); + //sleep_entry_register(&maclib_sleep_entry); + + ret = sys_mbox_new(&(maclib_mbox), 8); + if(0 != ret) { + LWIP_DEBUGF(NETIF_DEBUG,"msgbox init err!\r\n"); + goto mac_lib_err; + } +#if MACLIB_TASK_DEBUG + LWIP_DEBUGF(NETIF_DEBUG,"#mbox new\r\n"); +#endif + maclib_task_run = 1; + while(1) { + int mem_free = 1; + maclib_msg_t *msg = NULL; + unsigned int time = sys_arch_mbox_fetch(&(maclib_mbox), (void **)&msg, 0); + if ((SYS_ARCH_TIMEOUT == time) || (NULL == msg)) { + LWIP_DEBUGF(NETIF_DEBUG, "ml_task: invalid msg\r\n"); + continue; + } + switch(msg->type) { + case MACLIB_MSG_EVNT_HNDL: { + rda_critical_sec_start(); + g_event_proc_done = 0; + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#get event %d\r\n", g_event_num); +#endif + maclib_func_p->ml_tasklet(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#5\r\n"); +#endif + rda_critical_sec_start(); +#if 0 + g_event_num--; + if(0 > g_event_num) { + mbed_error_printf("event handle err\r\n"); + } else +#endif + g_event_proc_done = 1; + if(0 < g_event_num) { +#if MACLIB_TASK_DEBUG + mbed_error_printf("#2-1\r\n"); +#endif + sys_mbox_trypost(&(maclib_mbox), msg); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#2-2\r\n"); +#endif + mem_free = 0; + } + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#pDone\r\n"); +#endif + break; + } + default: + break; + } + if (mem_free) { + free_msg_str(msg); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#4\r\n"); +#endif + } + } + +mac_lib_err: + LWIP_DEBUGF(NETIF_DEBUG,"MACLib exit!\r\n"); + osDelay(osWaitForever); +} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c new file mode 100644 index 0000000000..4c6febce9d --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c @@ -0,0 +1,509 @@ +/* Copyright (c) 2019 ARM Limited + * 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. + */ + +/****************************************************************************** + * @file rda5991h_wland.c + * @brief RDA5991H wlan driver for LWIP + * @version: V1.0 + * @date: 25. July 2016 + * + * @note + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/tcpip.h" +#include "netif/etharp.h" +#include "sys_arch.h" +#include "rda5991h_wland.h" +#include "cmsis.h" +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +#include "entropy_poll.h" +#else +#include "trng_api.h" +#endif +#include "gpio_api.h" +#include "gpio_irq_api.h" +#include "maclib_task.h" +#include "rda_sys_wrapper.h" +#include +#include +#include +#include + +/* Global variables */ +rda_enetdata_t r91h_wifidata; + +int wland_dbg_dump = WLAND_DBG_DUMP; +int wland_dbg_level = WLAND_DBG_LEVEL; +int wpa_dbg_dump = WPA_DBG_DUMP; +int wpa_dbg_level = WPA_DBG_LEBEL; +int wlandlib_dbg_level = WLANDLIB_DBG_LEVEL; +int hut_dbg_dump = HUT_DBG_DUMP; + +//#define CONFIG_DISABLE_ALL_INT +#define CRI_SEC_START_PRI_LEVEL 0xF8 +#define CRI_SEC_END_PRI_LEVEL 0x00 +static unsigned int g_critical_sec_counter = 0U; +#if defined(CONFIG_DISABLE_ALL_INT) +static unsigned int g_critical_ctxt_saved = 0U; +#endif /* CONFIG_DISABLE_ALL_INT */ +void *packet_rx_queue; + +/* Function statements */ +void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx); +void mbed_mac_address(char *mac); + +/** \brief Driver transmit and receive thread priorities + * + * Thread priorities for receive thread and TX cleanup thread. Alter + * to prioritize receive or transmit bandwidth. In a heavily loaded + * system or with LEIP_DEBUG enabled, the priorities might be better + * the same. */ +#define RX_PRIORITY (osPriorityNormal) +#define TX_PRIORITY (osPriorityNormal) +#define PHY_PRIORITY (osPriorityNormal) + +void rda_netif_down(int netif) +{ + if (netif == 0) { + netif_set_down(r91h_wifidata.netif_sta); + } else { + netif_set_down(r91h_wifidata.netif_ap); + } +} + +void rda_netif_link_down(int netif) +{ + rda_msg msg; + msg.type = 1; + msg.arg1 = 0; + rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever); +} + +void rda_netif_up(int netif) +{ + if (netif == 0) { + netif_set_up(r91h_wifidata.netif_sta); + } else { + netif_set_up(r91h_wifidata.netif_ap); + } +} + +void rda_netif_link_up(int netif) +{ + rda_msg msg; + msg.type = 1; + msg.arg1 = 1; + rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever); + return; +} + +void rda_netif_input(u8_t *data, u32_t len, int idx, int netif) +{ + if (netif == 0) { + r91h_wifiif_input(r91h_wifidata.netif_sta, data, len, idx++); + } else { + r91h_wifiif_input(r91h_wifidata.netif_ap, data, len, idx++); + } +} + +void rda_get_macaddr(u8_t *macaddr, int mode) +{ + mbed_mac_address((char *)macaddr); + if (mode == 1) { + if(macaddr[0] & 0x04) { + macaddr[0] &= 0xFB; + } else { + macaddr[0] |= 0x04; + } + } + return; +} + +void rda_critical_sec_start(void) +{ + if (__get_IPSR() == 0U) { + if (0U == g_critical_sec_counter) { +#if defined(CONFIG_DISABLE_ALL_INT) + g_critical_ctxt_saved = __disable_irq(); +#else /* CONFIG_DISABLE_ALL_INT */ + __set_BASEPRI(CRI_SEC_START_PRI_LEVEL); +#endif /* CONFIG_DISABLE_ALL_INT */ + } + g_critical_sec_counter++; + } +} + +void rda_critical_sec_end(void) +{ + if (__get_IPSR() == 0U) { + g_critical_sec_counter--; + if (0U == g_critical_sec_counter) { +#if defined(CONFIG_DISABLE_ALL_INT) + __set_PRIMASK(g_critical_ctxt_saved); +#else /* CONFIG_DISABLE_ALL_INT */ + __set_BASEPRI(CRI_SEC_END_PRI_LEVEL); +#endif /* CONFIG_DISABLE_ALL_INT */ + } + } +} + +void * rda_create_interrupt(unsigned int vec, unsigned int pri, void *isr) +{ + NVIC_SetPriority((IRQn_Type)vec, (uint32_t) pri); + NVIC_SetVector((IRQn_Type)vec, (uint32_t) isr); + + return NULL; +} + +void rda_delete_interrupt(unsigned int vec) +{ + NVIC_SetVector((IRQn_Type)vec, 0); +} + +void rda_enable_interrupt(unsigned int vec) +{ + NVIC_EnableIRQ((IRQn_Type)vec); +} + +void rda_disable_interrupt(unsigned int vec) +{ + NVIC_DisableIRQ((IRQn_Type)vec); +} + +/** \brief Allocates a pbuf and returns the data from the incoming packet. + * + * \param[in] netif the lwip network interface structure + * \param[in] idx index of packet to be read + * \return a pbuf filled with the received packet (including MAC header) + */ +static struct pbuf *r91h_low_level_input(struct netif *netif, u8_t *data, u32_t len, int idx) +{ + struct pbuf *p, *q; + u16_t index = 0; + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input enter, rxlen:%d\n", len)); + + /* Obtain the size of the packet and put it into the "len" + variable. */ + if(!len) { + return NULL; + } + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) { + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + /* load rx data from 96 to local mem_pool */ + MEMCPY(q->payload, &data[index], q->len); + index += q->len; + + if (index >= len) { + break; + } + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + /* Drop this packet */ + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + + return NULL; + } + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + * \param[in] netif the lwip network interface structure + * \param[in] idx index of packet to be read + */ +void *data_sem = NULL; +void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx) +{ + if(data_sem == NULL) + data_sem = rda_sem_create(0); + rda_msg msg; + msg.type = 0; + msg.arg1 = (int)data; + msg.arg2 = len; + msg.arg3 = (int)data_sem; + rda_mail_put(packet_rx_queue, (void*)&msg, osWaitForever); + rda_sem_wait(data_sem, osWaitForever); + return; +} + +/** \brief Low level init of the MAC and PHY. + * + * \param[in] netif Pointer to LWIP netif structure + */ + +static err_t low_level_init(struct netif *netif) +{ + static int init_flag = 0; + if (init_flag == 0) { + wland_reg_func(); + init_flag = 1; + } + return ERR_OK; +} + +/** + * This function is the ethernet packet send function. It calls + * etharp_output after checking link status. + * + * \param[in] netif the lwip network interface structure for this enetif + * \param[in] q Pointer to pbug to send + * \param[in] ipaddr IP address + * \return ERR_OK or error code + */ +err_t rda91h_etharp_output(struct netif *netif, struct pbuf *q, const ip_addr_t *ipaddr) +{ + /* Only send packet is link is up */ + if (netif->flags & NETIF_FLAG_LINK_UP) + return etharp_output(netif, q, ipaddr); + + return ERR_CONN; +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] netif the lwip network interface structure for this netif + * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +static err_t rda91h_low_level_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q; + + /* rda5996 initiate transfer */ + u32_t actual_txlen = 0; + u8_t **data; + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + data = (void*)wland_get_databuf(); + + if(data == NULL){ + LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); + return ERR_BUF; + } + + for(q = p; q != NULL; q = q->next) + { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + MEMCPY(&((*data)[actual_txlen+2]), q->payload, q->len);//reserve wid header length + actual_txlen += q->len; + if(actual_txlen > 1514 || actual_txlen > p->tot_len) + { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", + actual_txlen, p->tot_len)); + return ERR_BUF; + } + } + + /* Signal rda5996 that packet should be sent */ + if(actual_txlen == p->tot_len) + { + if(netif->name[0] == 's' && netif->name[1] == 't') { + wland_txip_data((void*)data, actual_txlen, 0); + } else if(netif->name[0] == 'a' && netif->name[1] == 'p') { + wland_txip_data((void*)data, actual_txlen, 1); + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; + } + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", + actual_txlen, p->tot_len)); + + + return ERR_BUF; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. + * + * This function should be passed as a parameter to netif_add(). + * + * @param[in] netif the lwip network interface structure for this netif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t wifi_arch_enetif_init(struct netif *netif) +{ + err_t err; + static int thread_init_flag = 0; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + if (*((int *)netif->state) == 0) { + r91h_wifidata.netif_sta = netif; + netif->name[0] = 's'; + netif->name[1] = 't'; +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->hostname == NULL) + netif->hostname = "lwipr91h_sta"; +#endif /* LWIP_NETIF_HOSTNAME */ + rda_get_macaddr((u8_t *)(netif->hwaddr), 0); + } else if(*((int *)netif->state) == 1) { + r91h_wifidata.netif_ap = netif; + netif->name[0] = 'a'; + netif->name[1] = 'p'; +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->hostname == NULL) + netif->hostname = "lwipr91h_ap"; +#endif /* LWIP_NETIF_HOSTNAME */ + rda_get_macaddr((u8_t *)(netif->hwaddr), 1); + } + + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + // TODOETH: check if the flags are correct below + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + + /* Initialize the hardware */ + netif->state = &r91h_wifidata; + err = low_level_init(netif); + if (err != ERR_OK) + return err; + + netif->output = rda91h_etharp_output; + netif->linkoutput = rda91h_low_level_output; + if(thread_init_flag == 0){ + /* PHY monitoring task */ + sys_thread_new("maclib_thread", maclib_task, netif->state, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); + sys_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + thread_init_flag = 1; + } + return ERR_OK; +} + +unsigned char rda_mac_addr[6] = "\0"; +static int is_available_mac_addr(unsigned char *mac_addr) +{ + if (mac_addr[0]==0 && mac_addr[1]==0 && mac_addr[2]==0 && + mac_addr[3]==0 && mac_addr[4]==0 && mac_addr[5]==0) + return 0; + if (mac_addr[0]&0x1) + return 0; + return 1; +} +static void rda_get_macaddr_from_flash(unsigned char *macaddr) +{ + int ret; + if (!mac_is_valid((char *)rda_mac_addr)) { + ret = rda5981_flash_read_mac_addr(rda_mac_addr); + if ((ret!=0) || (is_available_mac_addr(rda_mac_addr)==0)) { +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + unsigned int out_len; + ret = mbedtls_hardware_poll(NULL, rda_mac_addr, 6, &out_len); + if (6 != out_len) { + LWIP_DEBUGF(NETIF_DEBUG, ("out_len err:%d\n", out_len)); + } +#else + ret = rda_trng_get_bytes(rda_mac_addr, 6); +#endif + rda_mac_addr[0] &= 0xfe; /* clear multicast bit */ + rda_mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ + rda5981_flash_write_mac_addr(rda_mac_addr); + } + } + memcpy(macaddr, rda_mac_addr, 6); +} +void mbed_mac_address(char *mac) +{ + mac[0] = 0xD6; + mac[1] = 0x71; + mac[2] = 0x36; + mac[3] = 0x60; + mac[4] = 0xD8; +#if !MBED_CONF_APP_ECHO_SERVER + mac[5] = 0xF4; +#else + mac[5] = 0xF3; +#endif + return; +} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c new file mode 100644 index 0000000000..35401ef3fe --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c @@ -0,0 +1,450 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if 1 +#include "sys_arch.h" +#include "cmsis_os.h" +#include "cmsis_os2.h" +#include "lwip/sys.h" +#include "rtx_lib.h" + +#include +#include +#include "mbed_assert.h" +#define NO_ERR 0 +#define ERR -1 + +//#define RDA_SYS_DEBUG +#ifdef RDA_SYS_DEBUG +#define RDA_SYS_PRINT(fmt, ...) do {\ + printf(fmt, ##__VA_ARGS__);\ + } while (0) +#else +#define RDA_SYS_PRINT(fmt, ...) +#endif + + +/* Alarm */ +// Timer definitions +#define osTimerInvalid 0 +#define osTimerStopped 1 +#define osTimerRunning 2 +#if 0 +// Timer structures, same as os_timer_cb(rt_CMSIS.c) +typedef struct rda_ostmr_cb { + struct rda_ostmr_cb *next; // Pointer to next active Timer + uint8_t state; // Timer State + uint8_t type; // Timer Type (Periodic/One-shot) + uint16_t reserved; // Reserved + uint32_t tcnt; // Timer Delay Count + uint32_t icnt; // Timer Initial Count + void *arg; // Timer Function Argument + const osTimerDef_t *timer; // Pointer to Timer definition +} rda_ostmr_cb_t; +#endif +//#define USING_STDLIB + +#if !defined(USING_STDLIB) +typedef struct rda_tmr_node { + mbed_rtos_storage_timer_t _obj_mem; +} rda_tmr_node_t; + +typedef struct rda_tmr_ctrl { + unsigned char *buff; + unsigned char *state; + unsigned char max_node_num; + unsigned char node_size; + unsigned char node_cntr; + unsigned char last_freed_node_idx; +} rda_tmr_ctrl_t; + +#define MAX_ALARM_NUM (28) +#define WORD_ALIGN(n) (((n) + 0x03UL) & ~0x03UL) +#define MAX_ALARM_STAT_SIZE WORD_ALIGN(MAX_ALARM_NUM >> 3) +#define MAX_ALARM_MEM_SIZE (MAX_ALARM_NUM * WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)) + MAX_ALARM_STAT_SIZE) + +unsigned long g_alarm_buf[WORD_ALIGN(MAX_ALARM_MEM_SIZE) >> 2] = {0}; +rda_tmr_ctrl_t g_alarm_ctrl = { + (unsigned char *)g_alarm_buf + MAX_ALARM_STAT_SIZE, + (unsigned char *)g_alarm_buf, + MAX_ALARM_NUM, + WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)), + 0U, + 0U +}; + +__STATIC_INLINE unsigned char get_node_state(unsigned char *buf, unsigned char idx) +{ + unsigned char state, ofst; + ofst = (idx & 0x07U); + buf += (idx >> 3); + state = (*buf >> ofst) & 0x01U; + return state; +} + +__STATIC_INLINE void set_node_state(unsigned char *buf, unsigned char idx, unsigned char state) +{ + unsigned char ofst, tmp; + ofst = (idx & 0x07U); + buf += (idx >> 3); + tmp = *buf & (~(0x01U << ofst)); + *buf = tmp | (((state & 0x01U) << ofst)); +} + +static rda_tmr_node_t *get_tmr_node(void) +{ + rda_tmr_node_t *node = NULL; + unsigned char idx = g_alarm_ctrl.last_freed_node_idx; + if ((idx < g_alarm_ctrl.max_node_num) && (0U == get_node_state(g_alarm_ctrl.state, idx))) { + set_node_state(g_alarm_ctrl.state, idx, 1U); + node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); + g_alarm_ctrl.node_cntr++; + } else { + for (idx = 0U; idx < g_alarm_ctrl.max_node_num; idx++) { + if(0U == get_node_state(g_alarm_ctrl.state, idx)) { + set_node_state(g_alarm_ctrl.state, idx, 1U); + node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); + g_alarm_ctrl.node_cntr++; + break; + } + } + } + return node; +} + +static void put_tmr_node(rda_tmr_node_t *node) +{ + unsigned char *node_buf = (unsigned char *)node; + unsigned char idx = (node_buf - g_alarm_ctrl.buff) / g_alarm_ctrl.node_size; + if ((node_buf > g_alarm_ctrl.buff) && (idx < g_alarm_ctrl.max_node_num) && + (1U == get_node_state(g_alarm_ctrl.state, idx))) { + set_node_state(g_alarm_ctrl.state, idx, 0U); + g_alarm_ctrl.node_cntr--; + g_alarm_ctrl.last_freed_node_idx = idx; + } +} +#endif /* !USING_STDLIB */ + +/** + * @brief : get current time in units of micro second + * @param[in] : + * @param[out]: + * @return : return time value with uint32 type + */ +unsigned long rda_get_cur_time_ms(void) +{ + return sys_now(); +} + +/** + * @brief : create an alarm with given function, return timer handle + * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) + * @param[out]: + * @return : return timer handle, a pointer to the timer structure, non-zero is valid + */ +void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode) +{ + osTimerId_t handle; + mbed_rtos_storage_timer_t* _obj_mem = NULL; + MBED_ASSERT(func != NULL); + osTimerAttr_t attr = { 0 }; +#if defined(USING_STDLIB) + _obj_mem = (mbed_rtos_storage_timer_t*)malloc(sizeof(mbed_rtos_storage_timer_t)); +#else /* USING_STDLIB */ + _obj_mem = (mbed_rtos_storage_timer_t*)get_tmr_node(); +#endif /* USING_STDLIB */ + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(_obj_mem)); + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_timer_t); + //printf("hehehehe fun %p\r\n", func); + handle = osTimerNew((osTimerFunc_t)func, mode, (void *)data, &attr); + //printf("time cb %p handle %p\r\n", _obj_mem, handle); + MBED_ASSERT(handle != NULL); + return handle; +} + +void * rda_alarm_create(void *func, unsigned int data) +{ + return rda_alarm_create_v2(func, data, osTimerOnce); +} + +/** + * @brief : delete an alarm with given handle, then reset the handle + * @param[in] : *handle(pointer to the timer structure) + * @param[out]: **handle(address of the handle variable) + * @return : + */ +int rda_alarm_delete(void **handle) +{ + if (NULL != *handle) { + osTimerId timer_id = (osTimerId)(*handle); + osStatus retval = osTimerDelete(timer_id); + if (osOK == retval) { +#if defined(USING_STDLIB) + free(timer_id); +#else /* USING_STDLIB */ + put_tmr_node((rda_tmr_node_t *)timer_id); +#endif /* USING_STDLIB */ + *handle = NULL; + } else { + RDA_SYS_PRINT("Delete alarm error: %d\r\n", retval); + return ERR; + } + return NO_ERR; + } + return ERR; +} + +/** + * @brief : start an alarm, raise a function call after given timeout delay + * @param[in] : handle(pointer to the timer structure)/timeout(micro second) + * @param[out]: + * @return : + */ +int rda_alarm_start(void *handle, unsigned int timeout_ms) +{ + if (NULL != handle) { + osTimerId timer_id = (osTimerId)handle; + osStatus retval = osTimerStart(timer_id, (uint32_t)timeout_ms); + if (osOK != retval) { + RDA_SYS_PRINT("Start alarm error: %d\r\n", retval); + return ERR; + } + return NO_ERR; + } + return ERR; +} + +/** + * @brief : stop an alarm, will not raise a function call any more + * @param[in] : handle(pointer to the timer structure) + * @param[out]: + * @return : + */ +int rda_alarm_stop(void *handle) +{ + if (NULL != handle) { + osTimerId timer_id = (osTimerId)handle; + osStatus retval = osTimerStop(timer_id); + if (osOK != retval) { + RDA_SYS_PRINT("Stop alarm error: %d\r\n", retval); + return ERR; + } + return NO_ERR; + } + return ERR; +} + + + +/* Semaphore */ +void* rda_sem_create(unsigned int count) +{ + osSemaphoreId_t sem; + mbed_rtos_storage_semaphore_t *_obj_mem = (mbed_rtos_storage_semaphore_t*)malloc(sizeof(mbed_rtos_storage_semaphore_t)); + osSemaphoreAttr_t attr = { 0 }; + attr.name = "rda_unnamed_sem"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_semaphore_t); + sem = osSemaphoreNew(1, count, &attr); + MBED_ASSERT(sem != NULL); + + return (void*)sem; +} + +int rda_sem_wait(void* sem, unsigned int millisec) +{ + int res; + + res = osSemaphoreWait(sem, millisec); + if (res > 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_wait error %d\r\n", res); + return ERR; + } +} + +int rda_sem_release(void *sem) +{ + int res; + + res = osSemaphoreRelease(sem); + if (res == 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_release error %d\r\n", res); + return ERR; + } +} + +int rda_sem_delete(void *sem) +{ + int res; + + res = osSemaphoreDelete(sem); + free(sem); + if (res == 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_delete error %d\r\n", res); + return ERR; + } +} + +/* Mail */ +void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize) +{ + unsigned int mq_size = msgcnt * (msgsize + sizeof(os_message_t)); + osMessageQueueId_t msgq; + mbed_rtos_storage_msg_queue_t *_obj_mem = (mbed_rtos_storage_msg_queue_t*)malloc(sizeof(mbed_rtos_storage_msg_queue_t)); + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_msg_queue_t)); + void *_mq_mem = (void *)malloc(mq_size); + MBED_ASSERT(_mq_mem != NULL); + memset(_mq_mem, 0, mq_size); + osMessageQueueAttr_t attr = { 0 }; + attr.name = "rda_unnamed_message_queue"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_msg_queue_t); + attr.mq_mem = _mq_mem; + attr.mq_size = mq_size; + msgq = osMessageQueueNew(msgcnt, msgsize, &attr); + MBED_ASSERT(msgq != NULL); + + return (void*)msgq; +} + +int rda_mail_get(void *msgq, void *msg, unsigned int wait) +{ + int ret; + ret = osMessageQueueGet(msgq, msg, 0, wait); + return ret; +} + +int rda_mail_put(void *msgq, void *msg, unsigned int wait) +{ + int ret; + ret = osMessageQueuePut(msgq, msg, 0, wait); + return ret; +} + +/* Mutex */ +void* rda_mutex_create(void) +{ + osMutexId_t rdamutex; + osMutexAttr_t attr = { 0 }; + mbed_rtos_storage_mutex_t *_obj_mem = (mbed_rtos_storage_mutex_t *)malloc(sizeof(mbed_rtos_storage_mutex_t)); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_mutex_t)); + attr.name = "rda_unnamed_mutex"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); + attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; + rdamutex = osMutexNew(&attr); + MBED_ASSERT(rdamutex != NULL); + return (void *)rdamutex; +} + +int rda_mutex_wait(void *rdamutex, unsigned int millisec) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexWait(mutex, millisec); + if (res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +int rda_mutex_realease(void *rdamutex) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexRelease(mutex); + if(res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +int rda_mutex_delete(void *rdamutex) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexDelete(mutex); + free(mutex); + if (res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +/* Thread */ +void* rda_thread_new(const char *pcName, + void (*thread)(void *arg), + void *arg, int stacksize, int priority) +{ + osThreadId_t id; + osThreadAttr_t _attr = { 0 }; + mbed_rtos_storage_thread_t *_obj_mem = (mbed_rtos_storage_thread_t *)malloc(sizeof(mbed_rtos_storage_thread_t)); + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_thread_t)); + _attr.priority = priority; + _attr.stack_size = stacksize; + _attr.name = pcName ? pcName : "rda_unnamed_thread"; + _attr.stack_mem = malloc(stacksize); + MBED_ASSERT(_attr.stack_mem != NULL); + _attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + _attr.cb_mem = _obj_mem; + _attr.tz_module = 0; + + //Fill the stack with a magic word for maximum usage checking + for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) { + ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5; + } + id = osThreadNew(thread, arg, &_attr); + if (id == NULL){ + free(_attr.stack_mem); + free(_attr.cb_mem); + RDA_SYS_PRINT("sys_thread_new create error\n"); + return NULL; + } + return (void *)id; +} + +int rda_thread_delete(void* id) +{ + osStatus ret; + unsigned int *stk = ((osRtxThread_t *)id)->stack_mem; + ret = osThreadTerminate(id); + free(id); + free(stk); + if (ret != osOK) { + return ERR; + } + return NO_ERR; +} + +void* rda_thread_get_id(void) +{ + osThreadId id = osThreadGetId(); + return (void*)id; +} +#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c new file mode 100644 index 0000000000..a2c0cd8ffa --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c @@ -0,0 +1,1481 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "critical.h" +#include "wland_flash.h" +#include "wland_dbg.h" +#include "rda5981_flash.h" +#include "wland_flash_wp.h" + +#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] + +u32 flash_size = FLASH_SIZE; +static u32 user_data_location = RDA5991H_USER_DATA_ADDR; +static u32 third_parter_data_location = RDA5991H_3RDPARTER_DATA_ADDR; +static u32 third_parter_data_len = RDA5991H_3RDPARTER_DATA_LEN; +int rda5981_read_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + char *temp_buf = NULL, *temp_buf_aligned; + + addr &= (flash_size -1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't read system data\n"); + return -1; + } + + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + ret = -1; + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + } else { + temp_buf_aligned = buf; + } + + core_util_critical_section_enter(); + spi_flash_flush_cache(); + SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + + if (temp_buf_aligned != buf) { + memcpy(buf, temp_buf_aligned, len); + } + +out: + if (temp_buf) { + free(temp_buf); + } + + return ret; +} + +void rda5981_spi_flash_erase_64KB_block(u32 addr) +{ + if (rda_ccfg_hwver() < 4) { + spi_wip_reset_2(); + spi_write_reset_2(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); + wait_busy_down_2(); + spi_wip_reset_2(); + } else { + spi_wip_reset_4(); + spi_write_reset_4(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); + wait_busy_down_4(); + spi_wip_reset_4(); + } +} +void rda5981_spi_erase_partition(void *src, u32 counts) +{ + u32 a4k, a64k, a64kend, a4kend, atmp; + + if (counts > 0x00) { + a4k = ((u32)src ) & (~((0x01UL << 12) - 0x01UL)); + a64k = ((u32)src + (0x01UL << 16) - 0x01UL) & (~((0x01UL << 16) - 0x01UL)); + a64kend = ((u32)src + counts ) & (~((0x01UL << 16) - 0x01UL)); + a4kend = ((u32)src + counts + (0x01UL << 12) - 0x01UL) & (~((0x01UL << 12) - 0x01UL)); + + for (atmp = a4k; atmp < a4kend; atmp += (0x01UL << 12)) { + if (a64kend > a64k) { + if (atmp == a64k) { + for (; atmp < a64kend; atmp += (0x01UL << 16)) { + core_util_critical_section_enter(); + rda5981_spi_flash_erase_64KB_block(atmp); + core_util_critical_section_exit(); + } + if (atmp == a4kend) { + break; + } + } + } + core_util_critical_section_enter(); + rda5981_spi_flash_erase_4KB_sector(atmp); + core_util_critical_section_exit(); + } + } +} +//@len must be 4k aligment +int rda5981_erase_flash(u32 addr, u32 len) +{ + WLAND_DBG(INFO, "erase flash :%x:%x\n", addr, len); + + addr &= (flash_size - 1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't erase system data\n"); + return -1; + } + + if (len & (SECTOR_SIZE-1)) { + len = ((len+SECTOR_SIZE) & (~(SECTOR_SIZE-1))); + } + flash_wrtie_protect(addr); + rda5981_spi_erase_partition((void*)addr, len); + flash_wrtie_protect_all(); + return 0; +} + +//@len must be 256 aligment +int rda5981_write_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + u8 *temp_buf = NULL, *temp_buf_aligned; + u8 *check_buf = NULL; + + addr &= (flash_size -1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't write system data\n"); + return -1; + } + + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + memcpy(temp_buf_aligned, buf, len); + } else { + temp_buf_aligned = (u8*)buf; + } + flash_wrtie_protect(addr); + core_util_critical_section_enter(); + //RDA5991H_ERASE_FLASH(addr, len); + RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + flash_wrtie_protect_all(); + +#ifdef FLASH_READ_CHECK + if (ret == 0) { + check_buf = malloc(len); + rda5981_read_flash(addr, check_buf, len); + if (memcmp(buf, check_buf, len) == 0) { + ret = 0; + } else { + ret = -1; + } + } +#endif /*FLASH_READ_CHECK*/ + +out: + if (temp_buf) { + free(temp_buf); + } + if (check_buf) { + free(check_buf); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +rda5991h_user_data wland_user_data; +u8 read_flag = 0; +int rda5981_write_user_data(u8 *data, u16 len, u32 flag) +{ + WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || + strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + memset(&wland_user_data, 0xff, sizeof(wland_user_data)); + wland_user_data.flag = flag; + strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); + } + + wland_user_data.flag |= flag; + + switch (flag) { + case RDA5991H_USER_DATA_FLAG_STA: + memcpy(&wland_user_data.sta_data, data, + min(sizeof(wland_user_data.sta_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_MAC: + memcpy(wland_user_data.mac_addr, data, + min(sizeof(wland_user_data.mac_addr), len)); + break; + case RDA5991H_USER_DATA_FLAG_PMK: + memcpy(wland_user_data.pmk, data, + min(sizeof(wland_user_data.pmk), len)); + break; + case RDA5991H_USER_DATA_FLAG_IP: + memcpy(wland_user_data.ip, data, + min(RDA5991H_USER_DATA_IP_LENGTH, len)); + break; + case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: + memcpy(&wland_user_data.parter_data_len, data, + min(sizeof(wland_user_data.parter_data_len), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER: + memcpy(&wland_user_data.tx_power, data, + min(sizeof(wland_user_data.tx_power), len)); + break; + case RDA5991H_USER_DATA_FLAG_XTAL_CAL: + memcpy(&wland_user_data.xtal_cal, data, + min(sizeof(wland_user_data.xtal_cal), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: + memcpy(&wland_user_data.tx_power_rf, data, + min(sizeof(wland_user_data.tx_power_rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: + memcpy(&wland_user_data.tx_power_phy_gn, data, + min(sizeof(wland_user_data.tx_power_phy_gn), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: + memcpy(&wland_user_data.tx_power_phy_b, data, + min(sizeof(wland_user_data.tx_power_phy_b), len)); + break; + case RDA5991H_USER_DATA_FLAG_AP: + memcpy(&wland_user_data.ap_data, data, + min(sizeof(wland_user_data.ap_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_APNET: + memcpy(&wland_user_data.ap_net_data, data, + min(sizeof(wland_user_data.ap_net_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_DHCP: + memcpy(&wland_user_data.dhcp, data, + min(sizeof(wland_user_data.dhcp), len)); + break; + case RDA5991H_USER_DATA_FLAG_UART: + memcpy(&wland_user_data.uart, data, + min(sizeof(wland_user_data.uart), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF: + memcpy(&wland_user_data.rf, data, + min(sizeof(wland_user_data.rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + memcpy(&wland_user_data.rf_channels, data, + min(sizeof(wland_user_data.rf_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY: + memcpy(&wland_user_data.phy, data, + min(sizeof(wland_user_data.phy), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + memcpy(&wland_user_data.phy_channels, data, + min(sizeof(wland_user_data.phy_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: + memcpy(&wland_user_data.tp_offset, data, + min(sizeof(wland_user_data.tp_offset), len)); + break; + default: + return -1; + } + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_erase_user_data(u32 flag) +{ + if (!read_flag) { + read_flag = 1; + rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + + if ((wland_user_data.flag & flag) == 0) { + return 0; + } + + wland_user_data.flag &= (~flag); + + if (wland_user_data.flag == 0) { + wland_user_data.flag = RDA5991H_USER_DATA_FLAG_UNINITIALIZED; + } + if (flag & RDA5991H_USER_DATA_FLAG_STA) { + memset(&wland_user_data.sta_data, 0xff, + sizeof(wland_user_data.sta_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_MAC) { + memset(wland_user_data.mac_addr, 0xff, + sizeof(wland_user_data.mac_addr)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PMK) { + memset(wland_user_data.pmk, 0xff, + sizeof(wland_user_data.pmk)); + } + if (flag & RDA5991H_USER_DATA_FLAG_IP) { + memset(wland_user_data.ip, 0xff, + RDA5991H_USER_DATA_IP_LENGTH); + } + if (flag & RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN) { + memset(&wland_user_data.parter_data_len, 0xff, + sizeof(wland_user_data.parter_data_len)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER) { + memset(&wland_user_data.tx_power, 0xff, + sizeof(wland_user_data.tx_power)); + } + if (flag & RDA5991H_USER_DATA_FLAG_XTAL_CAL) { + memset(&wland_user_data.xtal_cal, 0xff, + sizeof(wland_user_data.xtal_cal)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_RF) { + memset(&wland_user_data.tx_power_rf, 0xff, + sizeof(wland_user_data.tx_power_rf)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN) { + memset(&wland_user_data.tx_power_phy_gn, 0xff, + sizeof(wland_user_data.tx_power_phy_gn)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B) { + memset(&wland_user_data.tx_power_phy_b, 0xff, + sizeof(wland_user_data.tx_power_phy_b)); + } + if (flag & RDA5991H_USER_DATA_FLAG_AP) { + memset(&wland_user_data.ap_data, 0xff, + sizeof(wland_user_data.ap_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_APNET) { + memset(&wland_user_data.ap_net_data, 0xff, + sizeof(wland_user_data.ap_net_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_DHCP) { + memset(&wland_user_data.dhcp, 0xff, + sizeof(wland_user_data.dhcp)); + } + if (flag & RDA5991H_USER_DATA_FLAG_UART) { + memset(&wland_user_data.uart, 0xff, + sizeof(wland_user_data.uart)); + } + if (flag & RDA5991H_USER_DATA_FLAG_RF) { + memset(&wland_user_data.rf, 0xff, + sizeof(wland_user_data.rf)); + } + if (flag & RDA5991H_USER_DATA_FLAG_RF_CHANNELS) { + memset(&wland_user_data.rf_channels, 0xff, + sizeof(wland_user_data.rf_channels)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PHY) { + memset(&wland_user_data.phy, 0xff, + sizeof(wland_user_data.phy)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PHY_CHANNELS) { + memset(&wland_user_data.phy_channels, 0xff, + sizeof(wland_user_data.phy_channels)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET) { + memset(&wland_user_data.tp_offset, 0xff, + sizeof(wland_user_data.tp_offset)); + } + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_read_user_data(u8 *data, u16 len, u32 flag) +{ + //rda5991h_user_data wland_user_data; + WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); + + if (!read_flag) { + read_flag = 1; + rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + return -2; + } + if ((wland_user_data.flag & flag) == 0) { + return -3; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_STA: + memcpy(data, &wland_user_data.sta_data, + min(sizeof(wland_user_data.sta_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_MAC: + memcpy(data, wland_user_data.mac_addr, + min(sizeof(wland_user_data.mac_addr), len)); + break; + case RDA5991H_USER_DATA_FLAG_PMK: + memcpy(data, wland_user_data.pmk, + min(sizeof(wland_user_data.pmk), len)); + break; + case RDA5991H_USER_DATA_FLAG_IP: + memcpy(data, wland_user_data.ip, + min(RDA5991H_USER_DATA_IP_LENGTH, len)); + break; + case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: + memcpy(data, &wland_user_data.parter_data_len, + min(sizeof(wland_user_data.parter_data_len), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER: + memcpy(data, &wland_user_data.tx_power, + min(sizeof(wland_user_data.tx_power), len)); + break; + case RDA5991H_USER_DATA_FLAG_XTAL_CAL: + memcpy(data, &wland_user_data.xtal_cal, + min(sizeof(wland_user_data.xtal_cal), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: + memcpy(data, &wland_user_data.tx_power_rf, + min(sizeof(wland_user_data.tx_power_rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: + memcpy(data, &wland_user_data.tx_power_phy_gn, + min(sizeof(wland_user_data.tx_power_phy_gn), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: + memcpy(data, &wland_user_data.tx_power_phy_b, + min(sizeof(wland_user_data.tx_power_phy_b), len)); + break; + case RDA5991H_USER_DATA_FLAG_AP: + memcpy(data, &wland_user_data.ap_data, + min(sizeof(wland_user_data.ap_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_APNET: + memcpy(data, &wland_user_data.ap_net_data, + min(sizeof(wland_user_data.ap_net_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_DHCP: + memcpy(data, &wland_user_data.dhcp, + min(sizeof(wland_user_data.dhcp), len)); + break; + case RDA5991H_USER_DATA_FLAG_UART: + memcpy(data, &wland_user_data.uart, + min(sizeof(wland_user_data.uart), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF: + memcpy(data, &wland_user_data.rf, + min(sizeof(wland_user_data.rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + memcpy(data, &wland_user_data.rf_channels, + min(sizeof(wland_user_data.rf_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY: + memcpy(data, &wland_user_data.phy, + min(sizeof(wland_user_data.phy), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + memcpy(data, &wland_user_data.phy_channels, + min(sizeof(wland_user_data.phy_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: + memcpy(data, &wland_user_data.tp_offset, + min(sizeof(wland_user_data.tp_offset), len)); + break; + default: + return -1; + } + return 0; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_mac_addr(u8 *mac_addr) +{ + int ret; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); + if (ret) { + WLAND_DBG(ERROR, "read mac addr from flash fail\r\n"); + } else { + WLAND_DBG(INFO, "Done(ret:%d)"MACDBG"\r\n", ret, MAC2STRDBG(mac_addr)); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_mac_addr(u8 *mac_addr) +{ + WLAND_DBG(INFO, "Enter"MACDBG"\r\n", MAC2STRDBG(mac_addr)); + return rda5981_write_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_uart(void) +{ + return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_UART); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_uart(u32 *uart) +{ + int ret; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); + if (ret) { + WLAND_DBG(ERROR, "read uart setting from flash fail\r\n"); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_uart(u32 *uart) +{ + return rda5981_write_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_sta_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK | + RDA5991H_USER_DATA_FLAG_STA); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_sta_data(char *ssid, char *passwd) +{ + int ret; + wland_sta_data_t sta_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); + if (ret == 0) { + strcpy(ssid, sta_data.ssid); + strcpy(passwd, sta_data.key); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +extern u8 *rda_get_bssinfo_pmk(void); +extern u8 *rda_get_bssinfo_SSID(void); +int rda5981_flash_write_sta_data(const char *ssid, const char *passwd) +{ + int ret = 0, ret1; + wland_sta_data_t sta_data; + u8 *pbss_info_pmk = NULL, *pbss_info_SSID = NULL; + pbss_info_pmk = rda_get_bssinfo_pmk(); + pbss_info_SSID = rda_get_bssinfo_SSID(); + + WLAND_DBG(INFO, "Enter:ssid:%s,pw:%s, pmk:%02x %02x***\r\n", + ssid, passwd, pbss_info_pmk[0], pbss_info_SSID[1]); + if (strlen(ssid) == 0) { + WLAND_DBG(ERROR, "ssid is NULL\n"); + return -1; + } + + memset(&sta_data, 0xff, sizeof(sta_data)); + strcpy(sta_data.ssid, ssid); + strcpy(sta_data.key, passwd); + if (pbss_info_pmk[0] && memcmp(pbss_info_SSID, ssid, 6)==0) { + ret = rda5981_write_user_data(pbss_info_pmk, sizeof(pbss_info_pmk), RDA5991H_USER_DATA_FLAG_PMK); + } + ret1 = rda5981_write_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); + return ret || ret1;; +} + + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_dhcp_data(void) +{ + int ret;//, ret1; + //WLAND_DBG(INFO, "Enter\r\n"); + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_DHCP); + //ret1 = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_dhcp_data(unsigned int *fixip, unsigned int *ip, unsigned int *msk, unsigned int *gw) +{ + int ret; + wland_dhcp_t dhcp; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); + if (ret == 0) { + *fixip = dhcp.fixip; + *ip = dhcp.ip; + *msk = dhcp.msk; + *gw = dhcp.gw; + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_dhcp_data(unsigned int fixip, unsigned int ip, unsigned int msk, unsigned int gw) +{ + int ret = 0; + wland_dhcp_t dhcp; + + memset(&dhcp, 0xff, sizeof(dhcp)); + dhcp.fixip = fixip; + dhcp.ip = ip; + dhcp.msk = msk; + dhcp.gw = gw; + ret = rda5981_write_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); + return ret; +} + + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_ap_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_AP); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel) +{ + int ret = 0; + wland_ap_data_t ap_data; + + if (strlen(ssid) == 0) { + WLAND_DBG(ERROR, "ssid is NULL\n"); + return -1; + } + + memset(&ap_data, 0xff, sizeof(ap_data)); + strcpy(ap_data.ssid, ssid); + strcpy(ap_data.key, passwd); + ap_data.channel = channel; + ret = rda5981_write_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel) +{ + int ret; + wland_ap_data_t ap_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); + if (ret == 0) { + strcpy(ssid, ap_data.ssid); + strcpy(passwd, ap_data.key); + *channel = ap_data.channel; + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_ap_net_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_APNET); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, + unsigned int dhcps, unsigned int dhcpe) +{ + int ret = 0; + wland_ap_net_data_t ap_net_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + memset(&ap_net_data, 0xff, sizeof(ap_net_data)); + ap_net_data.ip = ip; + ap_net_data.msk = msk; + ap_net_data.gw = gw; + ap_net_data.dhcps = dhcps; + ap_net_data.dhcpe = dhcpe; + + ret = rda5981_write_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, + unsigned int *dhcps, unsigned int *dhcpe) +{ + int ret = 0; + wland_ap_net_data_t ap_net_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); + if (ret == 0) { + *ip = ap_net_data.ip; + *msk = ap_net_data.msk; + *gw = ap_net_data.gw; + *dhcps = ap_net_data.dhcps; + *dhcpe = ap_net_data.dhcpe; + } + return ret; +} + + +int rda5981_flash_read_pmk(u8 *pmk) +{ + WLAND_DBG(INFO, "Enter\r\n"); + return rda5981_read_user_data(pmk, 32, RDA5991H_USER_DATA_FLAG_PMK); +} + +int rda5981_flash_read_ip_addr(u8 *ip_addr, u8 *server_addr) +{ + int ret; + u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); + if (ret) { + WLAND_DBG(ERROR, "read ip addr from flash fail\r\n"); + } else { + memcpy(ip_addr, buf, 4); + memcpy(server_addr, buf+4, 4); + WLAND_DBG(INFO, "read ip:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + } + return ret; +} + +int rda5981_flash_write_ip_addr(u8 *ip_addr, u8 *server_addr) +{ + u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; + WLAND_DBG(INFO, "write:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + memcpy(buf, ip_addr, 4); + memcpy(buf+4, server_addr, 4); + return rda5981_write_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); +} + +int rda5981_flash_read_3rdparter_data_length() +{ + int ret; + u32 data_len = 0; + + WLAND_DBG(INFO, "Enter\r\n"); + ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); + return -1; + } + return data_len; +} + +int rda5981_flash_read_3rdparter_data(u8 *buf, u32 buf_len) +{ + int ret; + u32 data_len = 0; + + WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); + ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); + return -1; + } + + if (buf_len < data_len) + WLAND_DBG(ERROR, "The buf you prepared is to small(%u:%u)\r\n", buf_len, data_len); + + data_len = min(buf_len, data_len); + + ret = rda5981_read_flash(third_parter_data_location, + (char *)(buf), data_len); + if (ret) { + WLAND_DBG(ERROR, "read parter data from flash fail(%d)\r\n", ret); + return -2; + } + + return data_len; +} + +int rda5981_flash_erase_3rdparter_data() +{ + return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); +} + +int rda5981_flash_write_3rdparter_data(const u8 *buf, u32 buf_len) +{ + int ret; + + WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); + if (buf_len > third_parter_data_len) { + WLAND_DBG(ERROR, "buf too long(%u), we have only %x flash space\r\n", + buf_len, third_parter_data_len); + return -1; + } + + rda5981_erase_flash(third_parter_data_location, buf_len); + ret = rda5981_write_flash(third_parter_data_location, + (char *)(buf), buf_len); + if (ret) { + WLAND_DBG(ERROR, "write parter data to flash fail\r\n"); + return -2; + } + + ret = rda5981_write_user_data((u8 *)(&buf_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "write parter data length to flash fail\r\n"); + return -3; + } + return 0; +} + +int rda5981_set_flash_size(const u32 size) +{ + + WLAND_DBG(INFO, "Enter set flash size: %x\r\n", size); + if (size == 0x100000 || + size == 0x200000 || + size == 0x400000) { + flash_size = size; + return 0; + } + + return -1; +} + +int rda5981_set_user_data_addr(const u32 sys_data_addr, + const u32 user_data_addr, const u32 user_data_len) +{ + WLAND_DBG(INFO, "Enter set userdata addr: %x:%x:%x\r\n", + sys_data_addr, user_data_addr, user_data_len); + if ((sys_data_addr&(SECTOR_SIZE-1)) || (user_data_addr&(SECTOR_SIZE-1))) { + return -1; + } + if (sys_data_addr == user_data_addr) { + return -2; + } + + if (sys_data_addr<=0x18001000 || user_data_addr<=0x18001000) { + return -3; + } + if (sys_data_addr+0x1000 > 0x18000000+flash_size) { + return -4; + } + if (user_data_addr+user_data_len > 0x18000000+flash_size) { + return -5; + } + + user_data_location = sys_data_addr; + third_parter_data_location = user_data_addr; + third_parter_data_len= user_data_len; + return 0; +} + +int rda5981_write_user_data_regs(u8 *reg, u8 *value, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || + strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + memset(&wland_user_data, 0xff, sizeof(wland_user_data)); + wland_user_data.flag = flag; + strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); + } + + wland_user_data.flag |= flag; + + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + wland_user_data.rf.valid = 1; + wland_user_data.rf.flag = 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.rf.flag)) + return -2; + } + + if ((8 == idx) || (0 == wland_user_data.rf.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.rf.flag & BIT(idx))) { + wland_user_data.rf.reg_val[idx][0] = reg16; + wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); + wland_user_data.rf.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + wland_user_data.rf_channels.valid = 1; + wland_user_data.rf_channels.flag = 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.rf_channels.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.rf_channels.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.rf_channels.flag & BIT(idx))) { + wland_user_data.rf_channels.reg_val[idx][0] = reg16; + memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); + wland_user_data.rf_channels.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + wland_user_data.phy.valid = 1; + wland_user_data.phy.flag = 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.phy.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.phy.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.phy.flag & BIT(idx))) { + wland_user_data.phy.reg_val[idx][0] = reg32; + wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); + wland_user_data.phy.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + wland_user_data.phy_channels.valid = 1; + wland_user_data.phy_channels.flag = 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.phy_channels.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.phy_channels.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.phy_channels.flag & BIT(idx))) { + wland_user_data.phy_channels.reg_val[idx][0] = reg32; + memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); + wland_user_data.phy_channels.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +int rda5981_erase_user_data_regs(u8 *reg, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if ((wland_user_data.flag & flag) == 0) { + return 0; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + return 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + memset(&wland_user_data.rf.reg_val[idx][0], 0xFF, 2 * sizeof(u16)); + wland_user_data.rf.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.rf.flag) { + wland_user_data.rf.valid = 0xFFFFFFFF; + wland_user_data.rf.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + return 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memset(&wland_user_data.rf_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u16)); + wland_user_data.rf_channels.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.rf_channels.flag) { + wland_user_data.rf_channels.valid = 0xFFFFFFFF; + wland_user_data.rf_channels.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + return 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + memset(&wland_user_data.phy.reg_val[idx][0], 0xFF, 2 * sizeof(u32)); + wland_user_data.phy.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.phy.flag) { + wland_user_data.phy.valid = 0xFFFFFFFF; + wland_user_data.phy.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + return 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memset(&wland_user_data.phy_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u32)); + wland_user_data.phy_channels.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.phy_channels.flag) { + wland_user_data.phy_channels.valid = 0xFFFFFFFF; + wland_user_data.phy_channels.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + + +int rda5981_read_user_data_regs(u8 *reg, u8 *value, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if(0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + return -2; + } + if ((wland_user_data.flag & flag) == 0) { + return -3; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + return -4; + } + + reg16 = *((u16 *)reg); + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + memcpy(value, &wland_user_data.rf.reg_val[idx][1], sizeof(u16)); + break; + } else { + continue; + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + return -4; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memcpy(value, &wland_user_data.rf_channels.reg_val[idx][1], 14 * sizeof(u16)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + return -4; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + memcpy(value, &wland_user_data.phy.reg_val[idx][1], sizeof(u32)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + return -4; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memcpy(value, &wland_user_data.phy_channels.reg_val[idx][1], 14 * sizeof(u32)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + return 0; +} + +int rda5981_flash_get_mid(u8 *mid) +{ + *mid = 0xC8; + + return 0; +} + +int rda5981_flash_get_did(u8 *did) +{ + *did = 0x13; + + return 0; +} + +int rda5981_flash_get_jdid(u16 *jdid) +{ + *jdid = 0x4014; + + return 0; +} + +int rda5981_read_default_config(char *buf, u32 len, u32 flag) +{ + int ret = 0; + u32 addr; + u32 addr_offset = 0; + char *temp_buf = NULL, *temp_buf_aligned; + + switch (flag) { + case RDA5981_VBAT_CAL: + addr = 0x18000088; + break; + case RDA5981_GPADC0_CAL: + case RDA5981_GPADC1_CAL: + addr = 0x1800008C; + break; + case RDA5981_PRODUCT_ID: + addr = 0x18000084; + break; + case RDA5981_POWER_CLASS: + addr = 0x18000085; + break; + default: + WLAND_DBG(ERROR, "Unknown flag\n"); + return -1; + } + + addr_offset = addr % 4; + addr = (addr - addr_offset) & (flash_size -1); + + if (((u32)buf % 4) || (addr_offset != 0)) { + temp_buf = (char *)malloc(addr_offset + len + 4); + if (temp_buf == NULL) { + ret = -1; + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4 - (u32)temp_buf % 4); + } else { + temp_buf_aligned = temp_buf; + } + } else { + temp_buf_aligned = buf; + } + + core_util_critical_section_enter(); + spi_flash_flush_cache(); + SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, (len + addr_offset)); + core_util_critical_section_exit(); + + if (temp_buf_aligned != buf) { + memcpy(buf, temp_buf_aligned + addr_offset, len); + } +out: + if (temp_buf) { + free(temp_buf); + } + return ret; +} + +int rda5981_flash_read_vbat_cal(float *k, float *b) +{ + int ret = 0; + u32 value = 0; + u32 x1 = 0;//y1 3.0f + u32 x2 = 0;//y2 4.2f + float k_tmp = 0; + float b_tmp = 0; + + ret = rda5981_read_default_config((char *)&value, 4, RDA5981_VBAT_CAL); + + if (ret < 0) { + WLAND_DBG(ERROR, "read vbat_cal form flash fail\n"); + return -1; + } + if ((0 == (value & 0xFFFFFUL)) || (0xFFFFFUL == (value & 0xFFFFFUL))) { + WLAND_DBG(ERROR, "invalid vbat_cal:0x%08x\n", value); + return -1; + } else { + x1 = value & 0x3FFUL; + x2 = (value >> 10) & 0x3FFUL; + } + + if (x1 == x2) { + return -1; + } + + k_tmp = (4.2f - 3.0f) / (float)(x2 - x1); + b_tmp = 4.2f - k_tmp * x2; + + *k = k_tmp; + *b = b_tmp; + + return ret; +} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c new file mode 100644 index 0000000000..6ff0181640 --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c @@ -0,0 +1,366 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed_interface.h" +#include "wland_flash.h" + +//#define FLASH_PROTECT_ENABLE + +#define FLASH_CTL_REG_BASE 0x17fff000 +#define FLASH_CTL_TX_CMD_ADDR_REG (FLASH_CTL_REG_BASE + 0x00) +#define FLASH_CTL_TX_BLOCK_SIZE_REG (FLASH_CTL_REG_BASE + 0x04) +#define FLAHS_CTL_TX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x08) +#define FLASH_CTL_STATUS_REG (FLASH_CTL_REG_BASE + 0x0c) +#define FLAHS_CTL_RX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x10) + +#define WRITE_REG32(REG, VAL) ((*(volatile unsigned int*)(REG)) = (unsigned int)(VAL)) +#define WRITE_REG8(REG, VAL) ((*(volatile unsigned char*)(REG)) = (unsigned char)(VAL)) +#define MREAD_WORD(addr) *((volatile unsigned int *)(addr)) + +#define MID_GD 0xC8 +#define MID_WINBOND 0xEF + +#define FLASH_1M 0x100000 +#define FLASH_2M 0x200000 +#define FLASH_4M 0x400000 +extern unsigned int flash_size; + +#ifdef FLASH_PROTECT_ENABLE + +#define FLASH_WP_MASK 0x407c +#define FLASH_WP_NONE 0x0000 +#define FLASH_WP_ALL 0x1c + +#define FLASH_4M_WP_4K 0x0064 +#define FLASH_4M_WP_8K 0x0068 +#define FLASH_4M_WP_16K 0x006c +#define FLASH_4M_WP_32K 0x0070 +#define FLASH_4M_WP_1_64 0x0024 +#define FLASH_4M_WP_1_32 0x0028 +#define FLASH_4M_WP_1_16 0x002c +#define FLASH_4M_WP_1_8 0x0030 +#define FLASH_4M_WP_1_4 0x0034 +#define FLASH_4M_WP_1_2 0x0038 +#define FLASH_4M_WP_3_4 0x4014 +#define FLASH_4M_WP_7_8 0x4010 +#define FLASH_4M_WP_15_16 0x400c +#define FLASH_4M_WP_31_32 0x4008 +#define FLASH_4M_WP_63_64 0x4004 +#define FLASH_4M_WP_127_128 0x4058 +#define FLASH_4M_WP_255_256 0x404C +#define FLASH_4M_WP_1023_1024 0x4044 + +#define FLASH_2M_WP_4K 0x0064 +#define FLASH_2M_WP_8K 0x0068 +#define FLASH_2M_WP_16K 0x006c +#define FLASH_2M_WP_32K 0x0070 +#define FLASH_2M_WP_1_32 0x0024 +#define FLASH_2M_WP_1_16 0x0028 +#define FLASH_2M_WP_1_8 0x002c +#define FLASH_2M_WP_1_4 0x0050 +#define FLASH_2M_WP_1_2 0x0051 +#define FLASH_2M_WP_3_4 0x4010 +#define FLASH_2M_WP_7_8 0x400c +#define FLASH_2M_WP_15_16 0x4004 +#define FLASH_2M_WP_31_32 0x4000 +#define FLASH_2M_WP_63_64 0x4050 +#define FLASH_2M_WP_127_128 0x404c +#define FLASH_2M_WP_255_256 0x4048 +#define FLASH_2M_WP_511_512 0x4044 + + +#define FLASH_1M_WP_4K 0x0064 +#define FLASH_1M_WP_8K 0x0068 +#define FLASH_1M_WP_16K 0x006c +#define FLASH_1M_WP_32K 0x0070 +#define FLASH_1M_WP_1_16 0x0024 +#define FLASH_1M_WP_1_8 0x0028 +#define FLASH_1M_WP_1_4 0x002c +#define FLASH_1M_WP_1_2 0x0050 +#define FLASH_1M_WP_3_4 0x400C +#define FLASH_1M_WP_7_8 0x4008 +#define FLASH_1M_WP_15_16 0x4004 +#define FLASH_1M_WP_31_32 0x4050 +#define FLASH_1M_WP_63_64 0x404C +#define FLASH_1M_WP_127_128 0x4048 +#define FLASH_1M_WP_255_256 0x4044 + +static unsigned short flash_wrtie_protect_4M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + if (offset >= flash_size - flash_size/1024) { + wp = FLASH_4M_WP_1023_1024; + } else if(offset >= flash_size - flash_size/256) { + wp = FLASH_4M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_4M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_4M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_4M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_4M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_4M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_4M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_4M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_4M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_4M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_4M_WP_1_16; + } else if(offset >= flash_size/32) { + wp = FLASH_4M_WP_1_32; + } else if(offset >= flash_size/64) { + wp = FLASH_4M_WP_1_64; + } else if(offset >= 32 * 1024) { + wp = FLASH_4M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_4M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_4M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_4M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +static unsigned short flash_wrtie_protect_2M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + if (offset >= flash_size - flash_size/256) { + wp = FLASH_2M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_2M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_2M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_2M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_2M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_2M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_2M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_2M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_2M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_2M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_2M_WP_1_16; + } else if(offset >= flash_size/32) { + wp = FLASH_2M_WP_1_32; + } else if(offset >= 32 * 1024) { + wp = FLASH_2M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_2M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_2M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_2M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +static unsigned short flash_wrtie_protect_1M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + + if (offset >= flash_size - flash_size/256) { + wp = FLASH_1M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_1M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_1M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_1M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_1M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_1M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_1M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_1M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_1M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_1M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_1M_WP_1_16; + } else if(offset >= 32 * 1024) { + wp = FLASH_1M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_1M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_1M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_1M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +void flash_wrtie_protect_all() +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + status = (status & ~FLASH_WP_MASK) | FLASH_WP_ALL; + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} + +void flash_wrtie_protect_none() +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + status = status & ~FLASH_WP_MASK; + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} + +void flash_wrtie_protect(unsigned int offset) +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + if (flash_size == FLASH_4M) { + status = flash_wrtie_protect_4M(status, offset); + } else if(flash_size == FLASH_2M) { + status = flash_wrtie_protect_2M(status, offset); + } else if(flash_size == FLASH_1M) { + status = flash_wrtie_protect_1M(status, offset); + } else [ + LWIP_DEBUGF(NETIF_DEBUG,"flash_size is error\r\n"); + } + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} +#else +void flash_wrtie_protect_all() +{ + return; +} + +void flash_wrtie_protect_none() +{ + return; +} + +void flash_wrtie_protect(unsigned int offset) +{ + return; +} + +#endif +void rda5981_flash_init() +{ + unsigned int status3, status4, status5; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); + status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + wait_busy_down(); + spi_wip_reset(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x9F); + wait_busy_down(); + //WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); + //wait_busy_down(); + status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + core_util_critical_section_exit(); + + if ((status5&0xff != 0x14) && (status5&0xff != 0x15) && (status5&0xff != 0x16)) { + mbed_error_printf("flash size error\r\n"); + return; + } + flash_size = (1 << (status5&0xff)); + flash_wrtie_protect_all(); + + return; +} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c new file mode 100644 index 0000000000..05a85abc0a --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wland_ota.h" +#include "wland_flash.h" +#include "rda5981_ota.h" +#include "wland_dbg.h" +#include "wland_types.h" +#include "critical.h" +#include +#include + +#define IMAGE_MAGIC 0xAEAE + +u32 wland_ota_partition_addr = 0; +u32 wland_ota_partition_len = 0; +u32 wland_crc_result = ~0UL; + +static u32 crc32(const u8 *p, u32 len, u32 crc) +{ + const u32 *crc32_tab = (const u32 *)CRC32_TABLE_ADDR; + + if (rda_ccfg_hwver() >= 4) { + crc32_tab = (const u32 *)CRC32_TABLE_ADDR_4; + } + /* Calculate CRC */ + while(len--) { + crc = crc32_tab[((crc & 0xFF) ^ *p++)] ^ (crc >> 8); + } + + return crc; +} + +static int rda5981_ota_erase_flash(u32 addr, u32 len) +{ + addr &= (flash_size -1); + rda5981_spi_erase_partition((void *)addr, len); + return 0; +} +//write without erase +static int rda5981_ota_write_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + u8 *temp_buf = NULL, *temp_buf_aligned; + + addr &= (flash_size -1); + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + memcpy(temp_buf_aligned, (unsigned char *)buf, len); + } else { + temp_buf_aligned = (u8 *)buf; + } + core_util_critical_section_enter(); + RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + +out: + if (temp_buf) { + free(temp_buf); + } + return ret; +} + +int rda5981_write_partition_start(u32 addr, u32 img_len) +{ + if (addr < 0x18001000 || addr+img_len>0x18000000+flash_size) { + WLAND_DBG(ERROR,"write partition start addr error. (0x%08x, %u)\r\n", addr, img_len); + return -1; + } + if (addr%0x1000 || img_len%0x1000) { + WLAND_DBG(ERROR,"write partition start length error.(mast be 4k alignment) (0x%08x, %u)\r\n", addr, img_len); + return -1; + } + + WLAND_DBG(INFO, "rda5981_write_partition_start:0x%08x, %u\r\n", addr, img_len); + wland_ota_partition_addr = addr; + wland_ota_partition_len = img_len; + wland_crc_result = ~0U; + + rda5981_ota_erase_flash(addr, img_len); + return 0; +} +int rda5981_write_partition(u32 offset, const u8 *buf, u32 len) +{ + if (wland_ota_partition_addr==0 || offset+len>wland_ota_partition_len) { + WLAND_DBG(ERROR,"write partition error. out of start addr(0x%08x, %u). (0x%08x, %u)\r\n", + wland_ota_partition_addr, wland_ota_partition_len, offset, len); + return -1; + } + if (len%0x400) { + WLAND_DBG(ERROR,"write partition length error.(mast be 1k alignment) (0x%08x, %u)\r\n", offset, len); + return -1; + } + WLAND_DBG(DEBUG, "rda5981_write_partition:0x%08x, %u.(%02x)\r\n", + wland_ota_partition_addr + offset, len, buf[0]); + wland_crc_result = crc32(buf, len, wland_crc_result); + + WLAND_DBG(DEBUG, "rda5981_write_partition: wland_crc_result 0x%08x\r\n", + wland_crc_result); + return rda5981_ota_write_flash(wland_ota_partition_addr + offset, (char *)buf, len); + //return rda5981_write_flash(wland_ota_partition_addr + offset, buf, len); +} +int rda5981_write_partition_end(void) +{ + WLAND_DBG(INFO, "check crc32:0x%08x, %u\r\n", wland_ota_partition_addr, wland_ota_partition_len); + if (wland_ota_partition_addr == 0) { + WLAND_DBG(ERROR,"OTA is not started\r\n"); + return -1; + } + core_util_critical_section_enter(); + spi_flash_flush_cache(); + //u32 crc32_check = crc32(wland_ota_partition_addr, wland_ota_partition_len, ~0U); + u32 crc32_check = bootrom_crc32((unsigned char *)wland_ota_partition_addr, wland_ota_partition_len); + core_util_critical_section_exit(); + WLAND_DBG(INFO, "rda5981_write_partition_end:0x%08x:0x%08x\r\n", wland_crc_result, crc32_check); + wland_ota_partition_addr = 0UL; + + if (crc32_check == wland_crc_result) { + return 0; + } else { + WLAND_DBG(ERROR,"check crc32 error\r\n"); + return -1; + } +} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp new file mode 100644 index 0000000000..9305f0daeb --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp @@ -0,0 +1,293 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "cmsis_os.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "mbed_shared_queues.h" +#include "netsocket/nsapi_types.h" +#include "lwip/arch.h" +#include "lwip/pbuf.h" +#include "rda5991h_wland.h" +#include "rda5981x_emac_config.h" +#include "rda5981x_emac.h" +#include "rda_sys_wrapper.h" +#include "maclib_task.h" + +#define RDA_HWADDR_SIZE (6) +#define RDA_ETH_MTU_SIZE 1500 +#define RDA_ETH_IF_NAME "st" + +#define RX_PRIORITY (osPriorityNormal) +#define TX_PRIORITY (osPriorityNormal) +#define PHY_PRIORITY (osPriorityNormal) + +extern void *packet_rx_queue; + +RDA5981x_EMAC::RDA5981x_EMAC() +{ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the memory buffer chain that is passed to the function. + * + * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return true if the packet could be sent + * false value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +bool RDA5981x_EMAC::link_out(emac_mem_buf_t *buf) +{ + emac_mem_buf_t *q, *p = buf; + + u32_t actual_txlen = 0; + u8_t **data = NULL; + u16_t retry = 400; + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); + + while ((data == NULL) && (retry-- > 0)) { + data = (u8_t**)wland_get_databuf(); + osThreadYield(); + } + if (data == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); + memory_manager->free(buf); + return false; + } + + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + memcpy(&((*data)[actual_txlen+2]), memory_manager->get_ptr(q), memory_manager->get_len(q));//reserve wid header length + actual_txlen += memory_manager->get_len(q); + if (actual_txlen > 1514 || actual_txlen > memory_manager->get_total_len(p)) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", actual_txlen, memory_manager->get_total_len(p))); + memory_manager->free(buf); + return false; + } + } + + /* Signal rda5996 that packet should be sent */ + if (actual_txlen == memory_manager->get_total_len(p)) { + wland_txip_data((void*)data, actual_txlen, 0); + memory_manager->free(buf); + return true; + } + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", + actual_txlen, memory_manager->get_total_len(p))); + + memory_manager->free(buf); + return false; +} + +/** + * Should allocate a contiguous memory buffer and transfer the bytes of the incoming + * packet to the buffer. + * + * @param buf If a frame was received and the memory buffer allocation was successful, a memory + * buffer filled with the received packet (including MAC header) + * @return negative value when no more frames, + * zero when frame is received + */ +emac_mem_buf_t * RDA5981x_EMAC::low_level_input(u8_t *data, int len) +{ + emac_mem_buf_t *p, *q; + u16_t index = 0; + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input enter, rxlen:%d\n", len)); + + /* Obtain the size of the packet and put it into the "len" + variable. */ + if (!len) { + return NULL; + } + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = memory_manager->alloc_pool(len, 0); + if (p != NULL) { + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + /* load rx data from 96 to local mem_pool */ + memcpy(memory_manager->get_ptr(q), &data[index], memory_manager->get_len(q)); + index += memory_manager->get_len(q); + + if (index >= len) { + break; + } + } + + } else { + /* Drop this packet */ + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); + + return NULL; + } + return p; +} + + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +void RDA5981x_EMAC::packet_rx() +{ + rda_msg msg; + packet_rx_queue = rda_mail_create(10, sizeof(unsigned int)*4); + /* move received packet into a new buf */ + while (1) { + emac_mem_buf_t *p = NULL; + rda_mail_get(packet_rx_queue, (void*)&msg, osWaitForever); + switch(msg.type) { + case 0: + p = low_level_input((unsigned char*)msg.arg1, msg.arg2); + if (p == NULL) { + rda_sem_release((void*)msg.arg3); + break; + } + rda_sem_release((void*)msg.arg3); + if (p) { + emac_link_input_cb(p); + } + break; + case 1: + emac_link_state_cb(msg.arg1); + break; + default: + break; + } + } +} + +void RDA5981x_EMAC::thread_function(void *pvParameters) +{ + static struct RDA5981x_EMAC *rda5981x_enet = static_cast(pvParameters); + rda5981x_enet->packet_rx(); +} + +bool RDA5981x_EMAC::power_up() +{ + /* Initialize the hardware */ + static int init_flag = 0; + if (init_flag == 0) { + wland_reg_func(); + rda_thread_new("maclib_thread", maclib_task, NULL, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); + rda_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + rda_thread_new("packet_rx", RDA5981x_EMAC::thread_function, this, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(100); + wland_sta_init(); + init_flag = 1; + } + + return true; +} + +uint32_t RDA5981x_EMAC::get_mtu_size() const +{ + return RDA_ETH_MTU_SIZE; +} + +uint32_t RDA5981x_EMAC::get_align_preference() const +{ + return 0; +} + +void RDA5981x_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, RDA_ETH_IF_NAME, (size < sizeof(RDA_ETH_IF_NAME)) ? size : sizeof(RDA_ETH_IF_NAME)); +} + +uint8_t RDA5981x_EMAC::get_hwaddr_size() const +{ + return RDA_HWADDR_SIZE; +} + +bool RDA5981x_EMAC::get_hwaddr(uint8_t *addr) const +{ + mbed_mac_address((char *)addr); + return true; +} + +void RDA5981x_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void RDA5981x_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void RDA5981x_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::power_down() +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +RDA5981x_EMAC &RDA5981x_EMAC::get_instance() +{ + static RDA5981x_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return RDA5981x_EMAC::get_instance(); +} + diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h new file mode 100644 index 0000000000..62fda7374d --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h @@ -0,0 +1,161 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32_EMAC_H_ +#define STM32_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class RDA5981x_EMAC : public EMAC { +public: + RDA5981x_EMAC(); + + static RDA5981x_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); + +private: + void packet_rx(); + emac_mem_buf_t * low_level_input(u8_t *data, int len); + static void thread_function(void *pvParameters); + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + +}; + +#endif /* K64F_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h new file mode 100644 index 0000000000..717d423bfe --- /dev/null +++ b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define THREAD_STACKSIZE 512 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/targets/TARGET_RDA/TARGET_UNO_91H/device/RDA5991H.h b/targets/TARGET_RDA/TARGET_UNO_91H/device/RDA5991H.h index 5427afc6a2..288faada83 100644 --- a/targets/TARGET_RDA/TARGET_UNO_91H/device/RDA5991H.h +++ b/targets/TARGET_RDA/TARGET_UNO_91H/device/RDA5991H.h @@ -1,27 +1,17 @@ -/****************************************************************************** - * @file RDA5991H.h - * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File for - * RDA RDA5991H Device Series - * @version: V1.09 - * @date: 07. June 2018 +/* Copyright (c) 2019 Unisoc Communications Inc. * - * @note - * Copyright (C) 2009 ARM Limited. All rights reserved. + * 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 * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. + * http://www.apache.org/licenses/LICENSE-2.0 * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - + * 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 __RDA5991H_H__ #define __RDA5991H_H__ diff --git a/targets/TARGET_RDA/TARGET_UNO_91H/trng_api.c b/targets/TARGET_RDA/TARGET_UNO_91H/trng_api.c index 810531b86b..295db4a6bf 100644 --- a/targets/TARGET_RDA/TARGET_UNO_91H/trng_api.c +++ b/targets/TARGET_RDA/TARGET_UNO_91H/trng_api.c @@ -118,4 +118,14 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l return ret; } +int rda_trng_get_bytes(unsigned char *output, size_t len) +{ + size_t temp; + trng_t trng_obj; + trng_init(&trng_obj); + int ret = trng_get_bytes(&trng_obj, output, len, &temp); + trng_free(&trng_obj); + return ret; +} + #endif diff --git a/targets/targets.json b/targets/targets.json index 6ce7b7ad2f..aa8286fd73 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -8061,7 +8061,7 @@ "inherits": ["Target"], "core": "Cortex-M4F", "public": true, - "extra_labels": ["RDA", "UNO_91H", "FLASH_CMSIS_ALGO"], + "extra_labels": ["RDA", "UNO_91H", "FLASH_CMSIS_ALGO", "RDA_EMAC"], "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "macros": ["TWO_RAM_REGIONS", "CMSIS_NVIC_VIRTUAL", "CMSIS_NVIC_VIRTUAL_HEADER_FILE=\"RDA5981_nvic_virtual.h\""], "device_has": [ @@ -8070,6 +8070,7 @@ "PORTOUT", "PORTINOUT", "INTERRUPTIN", + "EMAC", "SERIAL", "STDIO_MESSAGES", "PWMOUT", @@ -8083,7 +8084,10 @@ }, "UNO_91H": { "inherits": ["RDA5981X"], - "detect_code": ["8001"] + "detect_code": ["8001"], + "overrides": { + "network-default-interface-type" : "WIFI" + } }, "GD32_Target": { "inherits": ["Target"],