Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: X_NUCLEO_IDW01M1_AP_Test
Fork of X_NUCLEO_IDW01M1 by
SpwfSADevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 20015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /** 00018 ****************************************************************************** 00019 * @file SpwfSADevice.cpp 00020 * @author STMicroelectronics 00021 * @brief Implementation of SpwfSADevice class for Wi-Fi mbed 00022 ****************************************************************************** 00023 * @copy 00024 * 00025 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 00026 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 00027 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 00028 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 00029 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 00030 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 00031 * 00032 * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> 00033 ****************************************************************************** 00034 */ 00035 00036 00037 #include "SpwfSADevice.h" 00038 #include "wifi_module.h" 00039 00040 00041 #ifdef __cplusplus 00042 extern "C" { 00043 #endif 00044 00045 void Rx_irq_handler(void); 00046 void Wifi_scheduler(void); 00047 void Wifi_ticker(void); 00048 00049 #ifdef __cplusplus 00050 } 00051 #endif 00052 00053 extern void setSpwfSADevice(SpwfSADevice * dev); 00054 00055 #define FORMAT_HEX_STRING "0x%08x" 00056 #define HEX_STRING_LENGTH 11 00057 00058 /** 00059 * @brief SpwfSADevice constructor 00060 * @param tx: Pin USART TX 00061 * rx: Pin USART RX 00062 * rst: reset pin for Spwf module 00063 * wkup: reset pin for Spwf module 00064 * rts: Pin USART RTS 00065 * @retval none 00066 */ 00067 SpwfSADevice::SpwfSADevice(PinName tx, PinName rx, PinName rst, PinName wkup, PinName rts): 00068 uart_(tx,rx), 00069 term_(SERIAL_TX, SERIAL_RX), 00070 wakeup_(wkup, PIN_INPUT, PullNone, 0), 00071 rst_(rst, PIN_INPUT, PullNone, 1), 00072 rts_(rts, PIN_INPUT, PullUp, 0) 00073 { 00074 setSpwfSADevice(this); 00075 sync_wait_signal = false; 00076 wait_for_incoming_client = false; 00077 wait_for_socket_data = false; 00078 } 00079 00080 /** 00081 * @brief SpwfSADevice destructor 00082 * @param none 00083 * @retval none 00084 */ 00085 SpwfSADevice::~SpwfSADevice(void) 00086 { 00087 //de-constructor 00088 } 00089 00090 /** 00091 * @brief init function 00092 initializes timers, gpios, uart 00093 * @param none 00094 * @retval error value 00095 */ 00096 int SpwfSADevice::init(void) 00097 { 00098 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00099 Timer timer; 00100 00101 timer.start(); 00102 rst_.output(); 00103 wakeup_.output(); 00104 rts_.output(); 00105 00106 term_.baud(9600); 00107 term_.format(8, SerialBase::None, 1); 00108 00109 uart_.baud(115200); 00110 uart_.format(8, SerialBase::None, 1); 00111 uart_.set_flow_control(SerialBase::RTS, PA_12, NC);//RTSCTS 00112 uart_.attach(Rx_irq_handler, SerialBase::RxIrq); 00113 00114 config.power=wifi_active; 00115 config.power_level=max; 00116 config.dhcp=on;//use DHCP IP address 00117 config.ip_addr = "192.168.0.50"; 00118 config.netmask_addr = "255.255.255.0"; 00119 config.gateway_addr = "192.168.0.1"; 00120 config.dns_addr = "192.168.0.1"; 00121 00122 /*Initialize the tickers*/ 00123 wifi_isr.attach_us(Wifi_ticker, 1000); //decreasing the time period to 1ms may be causing overrun issue with UART?\ 00124 //UART error not evident but characters are sometimes missing in pipeline(ring_buffer)\ 00125 //specifically in the +WIND:25:WiFi Association with 'STM' successful WIND (why specifically this?) 00126 00127 wifi_callback.attach_us(Wifi_scheduler, 5000);//How low can we go? 00128 00129 sync_wait_signal = false; 00130 status = wifi_init(&config); 00131 if(status!=WiFi_MODULE_SUCCESS) 00132 { 00133 return -1; 00134 } 00135 while(!sync_wait_signal) 00136 { 00137 if (timer.read_ms() > _timeout) { 00138 return -1; 00139 } 00140 __NOP(); 00141 } 00142 00143 return 0; 00144 } 00145 00146 /** 00147 * @brief network connect 00148 wrapper function for FW 00149 * @param ssid: Access Point (AP) Name String 00150 * sec_key: Password String for AP 00151 * priv_mode: type of security supported (FW mode) 00152 * @retval NSAPI Error Type 00153 */ 00154 int SpwfSADevice::connect(char * ssid, char * sec_key, WiFi_Priv_Mode priv_mode) 00155 { 00156 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00157 Timer timer; 00158 00159 timer.start(); 00160 sync_wait_signal = false; 00161 status = wifi_connect(ssid, sec_key, priv_mode); 00162 if(status!=WiFi_MODULE_SUCCESS) 00163 { 00164 return -1; 00165 } 00166 00167 while(!sync_wait_signal) 00168 { 00169 if (timer.read_ms() > _timeout) { 00170 return -1; 00171 } 00172 __NOP(); 00173 } 00174 00175 return 0; 00176 } 00177 00178 /** 00179 * @brief start the mini access point 00180 * @param ssid: start with this SSID 00181 * @param sec_key: passphrase for STAtions to connect with 00182 * @param priv_mode: type of security to set up with 00183 * @param channel_num: WiFi channel to use 00184 * @param data_rates: bitmap of operational data rates to support 00185 * @retval NSAPI Error Type 00186 */ 00187 int SpwfSADevice::start_access_point(char * ssid, char * sec_key, WiFi_Priv_Mode priv_mode, int channel_num, unsigned int data_rates) 00188 { 00189 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00190 Timer timer; 00191 00192 timer.start(); 00193 00194 // Reset the data rate values 00195 uint32_t modeNEnabled = 1; 00196 char oprMask[] = "0x003fffcf"; 00197 if (0x3fffcf != data_rates) 00198 { 00199 // All data rates must be enabled to allow wireless N (high throughput/HT) mode 00200 modeNEnabled = 0; 00201 sprintf(oprMask, (const char*)FORMAT_HEX_STRING, data_rates); 00202 00203 // Different basic rate mask 00204 char basMask[HEX_STRING_LENGTH]; 00205 sprintf(basMask, FORMAT_HEX_STRING, data_rates & 0xf); 00206 status = SET_Configuration_Addr(WIFI_BAS_RATE_MASK, basMask); 00207 if(status != WiFi_MODULE_SUCCESS) return -1; 00208 } 00209 00210 status = SET_Configuration_Value(WIFI_HT_MODE, modeNEnabled); 00211 if(status != WiFi_MODULE_SUCCESS && modeNEnabled) { 00212 return -1; 00213 } 00214 status = SET_Configuration_Addr(WIFI_OPR_RATE_MASK, oprMask); 00215 if(status != WiFi_MODULE_SUCCESS) return -1; 00216 00217 // Start the access point 00218 sync_wait_signal = false; 00219 status = wifi_ap_start((uint8_t*)ssid, (uint8_t)channel_num); 00220 if(status!=WiFi_MODULE_SUCCESS) 00221 { 00222 return -1; 00223 } 00224 00225 while(!sync_wait_signal) 00226 { 00227 if (timer.read_ms() > _timeout) { 00228 return -1; 00229 } 00230 __NOP(); 00231 } 00232 00233 return 0; 00234 } 00235 00236 /** 00237 * @brief network disconnect 00238 wrapper function for FW 00239 * @param none 00240 * @retval error value 00241 */ 00242 int SpwfSADevice::disconnect() 00243 { 00244 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00245 00246 status = wifi_disconnect();//will set to Idle Mode 00247 if(status!=WiFi_MODULE_SUCCESS) 00248 { 00249 return -1; 00250 } 00251 00252 return 0; 00253 } 00254 00255 /** 00256 * @brief Get the local IP address 00257 * wrapper function for FW 00258 * @param none 00259 * @retval Null-terminated representation of the local IP address 00260 * or null if not yet connected 00261 */ 00262 const char *SpwfSADevice::getIPAddress() 00263 { 00264 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00265 00266 status = WiFi_Get_IP_Address((uint8_t *)_ip_buffer); 00267 00268 if(status!=WiFi_MODULE_SUCCESS) 00269 { 00270 return NULL; 00271 } else 00272 return _ip_buffer; 00273 } 00274 00275 /** 00276 * @brief Get the MAC address 00277 * wrapper function for FW 00278 * @param none 00279 * @retval Null-terminated representation of the MAC address 00280 * or null if not yet connected 00281 */ 00282 const char *SpwfSADevice::getMACAddress() 00283 { 00284 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00285 00286 status = WiFi_Get_MAC_Address((uint8_t *)_mac_buffer); 00287 00288 if(status!=WiFi_MODULE_SUCCESS) 00289 { 00290 return NULL; 00291 } else 00292 return _mac_buffer; 00293 } 00294 00295 /** 00296 * @brief connect to a remote socket 00297 * @param hostname: address of socket 00298 port_number: port number to connect 00299 protocol: TCP/UDP protocol 00300 * sock_id: pointer to socket ID returned by FW 00301 * @retval error value 00302 */ 00303 int SpwfSADevice::socket_client_open(uint8_t * hostname, uint32_t port_number, uint8_t * protocol, uint8_t * sock_id) 00304 { 00305 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00306 00307 //Timeout of synchronous functions? 00308 status = wifi_socket_client_open(hostname, port_number, protocol, sock_id); 00309 if(status!=WiFi_MODULE_SUCCESS) 00310 { 00311 *sock_id = 99;//make sure socket id is not set(set to out of bounds of SPWFSA_SOCKET_COUNT range) 00312 return -1; 00313 } 00314 00315 return 0; 00316 } 00317 00318 /** 00319 * @brief write to a remote socket 00320 * @param sock_id: FW ID of the socket 00321 DataLength: size of the data 00322 pData: pointer to data 00323 * @retval error value 00324 */ 00325 int SpwfSADevice::socket_client_write(uint8_t sock_id, uint16_t DataLength,char * pData) 00326 { 00327 int status=0;//number of bytes 00328 00329 status = wifi_socket_client_write(sock_id, DataLength, pData); 00330 //map error to enum ns_error_t 00331 00332 if(status > 0) 00333 { 00334 return status; 00335 } 00336 return 0; 00337 } 00338 00339 /** 00340 * @brief receive from a remote socket 00341 * @param sock_id: FW ID of the socket 00342 DataLength: size of the data 00343 pData: pointer to data 00344 * @retval error value 00345 */ 00346 int SpwfSADevice::socket_client_recv(uint8_t sock_id, uint16_t RecvLength,char * pData) 00347 { 00348 static Timer recv_timer; 00349 //char debug_str[10]; 00350 static bool recv_call = true; 00351 00352 if(recv_call) 00353 { 00354 //debug_print("\r\nrecv_call\r\n"); 00355 //__disable_irq(); 00356 wait_for_socket_data = false; 00357 recv_buff = (uint8_t*)pData; 00358 //__enable_irq(); 00359 if(_timeout>0) 00360 recv_timer.start(); 00361 recv_call = false; 00362 bytes_to_read = RecvLength; 00363 bytes_read=0; 00364 } 00365 00366 00367 if(wait_for_socket_data || recv_timer.read_ms() >= _timeout) 00368 { 00369 recv_call = true; 00370 _timeout = 0; 00371 wait_for_socket_data = true; 00372 recv_timer.stop(); 00373 recv_timer.reset(); 00374 wait_ms(1); 00375 if(bytes_read == 0) //<bytes_to_read?? 00376 return -1;//return error if no bytes are read! 00377 else 00378 return bytes_read;//return amount of data arrived so far 00379 } 00380 wait_ms(1); //CHECK:TODO: Need to wait to allow other IRQ's to run in case of non-blocking call? 00381 return -1; 00382 } 00383 00384 /** 00385 * @brief scan the network 00386 * @param scan_result: scan result data pointer 00387 max_scan_number: size of the scan result 00388 * @retval error value 00389 */ 00390 void SpwfSADevice::network_scan(wifi_scan *scan_result, uint16_t max_scan_number) 00391 { 00392 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00393 00394 status = wifi_network_scan(scan_result, max_scan_number); 00395 if(status!=WiFi_MODULE_SUCCESS) 00396 { 00397 return; 00398 } 00399 } 00400 00401 /** 00402 * @brief HTTP GET from remote host 00403 * @param hostname: address of remote host 00404 path: path to resource 00405 port_number: port number 00406 * @retval none 00407 */ 00408 void SpwfSADevice::http_get(uint8_t * hostname, uint8_t * path, uint32_t port_number) 00409 { 00410 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00411 00412 status = wifi_http_get((uint8_t *)hostname, (uint8_t *)path, port_number); 00413 if(status!=WiFi_MODULE_SUCCESS) 00414 { 00415 return; 00416 } 00417 } 00418 00419 /** 00420 * @brief HTTP GET from remote host 00421 * @param url_path: complete url of remote resource 00422 * @retval none 00423 */ 00424 void SpwfSADevice::http_post(uint8_t * url_path) 00425 { 00426 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00427 00428 status = wifi_http_post(url_path); 00429 if(status!=WiFi_MODULE_SUCCESS) 00430 { 00431 return; 00432 } 00433 } 00434 00435 /** 00436 * @brief FW callback with data in socket 00437 * @param sock_id: FW ID of the socket 00438 data_ptr: pointer to data from FW 00439 message_size: total data to arrive 00440 chunk_size: size of the data in this callback (<= message_size) 00441 * @retval none 00442 */ 00443 void SpwfSADevice::signal_data_receive(uint8_t socket_id, uint8_t * data_ptr, uint32_t message_size, uint32_t chunk_size) 00444 { 00445 char debug_str[50]; 00446 //Data will be copied or returned to user only if there is a pending request 00447 //Copy data to pData 00448 //sprintf((char*)debug_str,"sock_id: %d, size: %d, chunk: %d\r\n",socket_id, message_size, chunk_size); 00449 //debug_print(debug_str); 00450 00451 if(recv_buff && !wait_for_socket_data) 00452 { 00453 if((bytes_read + chunk_size)<= bytes_to_read) 00454 { 00455 memcpy(recv_buff + bytes_read, data_ptr, chunk_size);//only copy bytes_to_read asked by user//rest of the data is lost!! 00456 bytes_read += chunk_size; 00457 } 00458 else 00459 { 00460 uint32_t x_size = (bytes_read + chunk_size) - bytes_to_read; 00461 memcpy(recv_buff + bytes_read, data_ptr, chunk_size-x_size); 00462 bytes_read += (chunk_size-x_size); 00463 } 00464 00465 if(bytes_read >= bytes_to_read) 00466 { 00467 __disable_irq(); 00468 wait_for_socket_data = true; 00469 __enable_irq(); 00470 } 00471 } 00472 else 00473 { 00474 debug_print("\r\n Socket:: Data Dropped: "); 00475 sprintf((char*)debug_str,"%d\r\n",chunk_size); 00476 debug_print(debug_str); 00477 __disable_irq(); 00478 wait_for_socket_data = true; 00479 __enable_irq(); 00480 } 00481 } 00482 00483 /** 00484 * @brief synchronization function called from FW (used for connect,disconnect, ready, etc.) 00485 * @param code: Status code value returned 00486 * @retval none 00487 */ 00488 void SpwfSADevice::signal_synch_wait(WiFi_Status_t code) 00489 { 00490 if(code == WiFi_DISASSOCIATION) 00491 { 00492 //do nothing 00493 } 00494 else 00495 { 00496 __disable_irq(); 00497 sync_wait_signal = true; 00498 __enable_irq(); 00499 } 00500 } 00501 00502 /** 00503 * @brief close a client socket 00504 * @param sock_close_id: FW ID of the socket to close 00505 * @retval error value 00506 */ 00507 int SpwfSADevice::socket_client_close(uint8_t sock_close_id) 00508 { 00509 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00510 00511 status = wifi_socket_client_close(sock_close_id); 00512 //map error to enum ns_error_t 00513 if(status!=WiFi_MODULE_SUCCESS) 00514 { 00515 return -1; 00516 } 00517 00518 return 0; 00519 } 00520 00521 /** 00522 * @brief open a server socket 00523 * @param port_number: port number to listen on 00524 * protocol: TCP/UDP protocol 00525 * @retval error value 00526 */ 00527 int SpwfSADevice::socket_server_open(uint32_t port_number, uint8_t * protocol) 00528 { 00529 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00530 00531 status = wifi_socket_server_open(port_number, protocol); 00532 //map error to enum ns_error_t 00533 if(status!=WiFi_MODULE_SUCCESS) 00534 { 00535 return -1; 00536 } 00537 00538 return 0; 00539 } 00540 00541 /** 00542 * @brief write to a server socket 00543 * @param data_length: size of the data 00544 * pdata: pointer to data 00545 * @retval error value 00546 */ 00547 int SpwfSADevice::socket_server_write(uint16_t data_length,char * pdata) 00548 { 00549 int status = 0;//number of bytes 00550 00551 status = wifi_socket_server_write(data_length, pdata); 00552 //map error to enum ns_error_t 00553 if(status > 0) 00554 { 00555 return status; 00556 } 00557 return 0; 00558 } 00559 00560 /** 00561 * @brief close a server socket 00562 * @param none (only one server socket supported) 00563 * @retval error value 00564 */ 00565 int SpwfSADevice::socket_server_close(void) 00566 { 00567 WiFi_Status_t status = WiFi_MODULE_SUCCESS; 00568 00569 status = wifi_socket_server_close(); 00570 //map error to enum ns_error_t 00571 if(status!=WiFi_MODULE_SUCCESS) 00572 { 00573 return -1; 00574 } 00575 00576 return 0; 00577 } 00578 00579 /** 00580 * @brief attach/remove IRQ handler to UART 00581 * @param attach: attach/remove boolean 00582 * @retval none 00583 */ 00584 void SpwfSADevice::spwf_attach_irq(wifi_bool attach) 00585 { 00586 if(attach) 00587 { 00588 uart_.attach(Rx_irq_handler, SerialBase::RxIrq); 00589 } 00590 else 00591 { 00592 uart_.attach(NULL, SerialBase::RxIrq); 00593 } 00594 } 00595 00596 /** 00597 * @brief write byte(s) to the UART 00598 * @param cmd: pointer to data 00599 * size: size of data 00600 * @retval error value 00601 */ 00602 int SpwfSADevice::spwf_send(const char * cmd, uint16_t size) 00603 { 00604 Timer timer; 00605 int i, bytes; 00606 //timer.start(); 00607 00608 //uart_.puts(cmd);//string may contain '\0' character in between hence not used 00609 00610 for(i=0;i<size;i++) 00611 { 00612 uart_.putc(cmd[i]); 00613 //if (timer.read_ms() > _timeout) { 00614 //return -1; 00615 //} 00616 } 00617 00618 bytes = (int) size - 2;//we send 2 bytes extra for module 00619 return bytes; 00620 } 00621 00622 /** 00623 * @brief read a byte from the UART 00624 * @param none 00625 * @retval byte character 00626 */ 00627 char SpwfSADevice::spwf_get(void) 00628 { 00629 return(uart_.getc()); 00630 } 00631 00632 /** 00633 * @brief (re)set the SPWF wakeup GPIO pin 00634 * @param wake (re)set value 00635 * @retval none 00636 */ 00637 void SpwfSADevice::spwf_wakeup(int wake) 00638 { 00639 wakeup_.write(wake); 00640 } 00641 00642 /** 00643 * @brief (re)set the SPWF reset GPIO pin 00644 * @param reset (re)set value 00645 * @retval none 00646 */ 00647 void SpwfSADevice::spwf_reset(int reset) 00648 { 00649 rst_.write(reset); 00650 } 00651 00652 /** 00653 * @brief (re)set the SPWF RTS GPIO line 00654 * @param rts (re)set value 00655 * @retval none 00656 */ 00657 void SpwfSADevice::spwf_rts(int rts) 00658 { 00659 rts_.write(rts); 00660 } 00661 00662 /** 00663 * @brief read the SPWF RTS GPIO pin 00664 * @param none 00665 * @retval none 00666 */ 00667 int SpwfSADevice::spwf_read_rts() 00668 { 00669 return(rts_.read()); 00670 } 00671 00672 /** 00673 * @brief send debug print to serial terminal 00674 * @param string: data for debug print 00675 * @retval none 00676 */ 00677 void SpwfSADevice::debug_print(const char * string) 00678 { 00679 term_.puts(string); 00680 } 00681 00682 /** 00683 * @brief (re)set the switch for incoming client (server socket) 00684 * @param set: boolean to (re)set 00685 * @retval none 00686 */ 00687 void SpwfSADevice::set_wait_for_incoming_client(bool set) 00688 { 00689 wait_for_incoming_client = set; 00690 } 00691 00692 /** 00693 * @brief get the switch for incoming client (server socket) 00694 * @param none 00695 * @retval boolean 00696 */ 00697 bool SpwfSADevice::get_wait_for_incoming_client() 00698 { 00699 return wait_for_incoming_client; 00700 } 00701
Generated on Tue Jul 12 2022 12:20:21 by
1.7.2
