ST / X_NUCLEO_IDW01M1

Dependents:   SpwfInterface_NSAPI_Tests HelloWorld_IDW01M1

Fork of X_NUCLEO_IDW01M1 by ST Expansion SW Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SpwfSADevice.cpp Source File

SpwfSADevice.cpp

Go to the documentation of this file.
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>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
00033   ******************************************************************************
00034   */ 
00035   
00036 
00037 #include "SpwfSADevice.h" 
00038 
00039 
00040 #ifdef __cplusplus
00041 extern "C" {
00042 #endif
00043   
00044 void Rx_irq_handler(void);
00045 void Wifi_scheduler(void);
00046 void Wifi_ticker(void);
00047 
00048 #ifdef __cplusplus
00049 }
00050 #endif
00051 
00052 extern void setSpwfSADevice(SpwfSADevice * dev);
00053 
00054 /**
00055 * @brief  SpwfSADevice constructor         
00056 * @param  tx: Pin USART TX  
00057 *         rx: Pin USART RX
00058 *         rst: reset pin for Spwf module
00059 *         wkup: reset pin for Spwf module
00060 *         rts: Pin USART RTS
00061 * @retval none
00062 */
00063 SpwfSADevice::SpwfSADevice(PinName tx, PinName rx, PinName rst, PinName wkup, PinName rts):
00064     uart_(tx,rx), 
00065     term_(SERIAL_TX, SERIAL_RX),
00066     wakeup_(wkup, PIN_INPUT, PullNone, 0),
00067     rst_(rst, PIN_INPUT, PullNone, 1),     
00068     rts_(rts, PIN_INPUT, PullUp, 0)
00069 {
00070     setSpwfSADevice(this);
00071     sync_wait_signal = false;
00072     wait_for_incoming_client = false;
00073     wait_for_socket_data = false;
00074 }
00075 
00076 /**
00077 * @brief  SpwfSADevice destructor         
00078 * @param  none
00079 * @retval none
00080 */
00081 SpwfSADevice::~SpwfSADevice(void)
00082 {
00083     //de-constructor
00084 }
00085 
00086 /**
00087 * @brief  init function
00088           initializes timers, gpios, uart
00089 * @param  none
00090 * @retval error value
00091 */
00092 int SpwfSADevice::init(void) 
00093 {
00094     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00095     Timer timer;
00096     
00097     timer.start();    
00098     rst_.output();
00099     wakeup_.output();
00100     rts_.output();
00101     
00102     term_.baud(9600);
00103     term_.format(8, SerialBase::None, 1);
00104   
00105     uart_.baud(115200);
00106     uart_.format(8, SerialBase::None, 1);
00107     uart_.set_flow_control(SerialBase::RTS, PA_12, NC);//RTSCTS
00108     uart_.attach(Rx_irq_handler, SerialBase::RxIrq);
00109 
00110     config.power=wifi_active;
00111     config.power_level=high;
00112     config.dhcp=on;//use DHCP IP address
00113     
00114     /*Initialize the tickers*/
00115     wifi_isr.attach_us(Wifi_ticker, 1000); //decreasing the time period to 1ms may be causing overrun issue with UART?\
00116                                                 //UART error not evident but characters are sometimes missing in pipeline(ring_buffer)\
00117                                                 //specifically in the +WIND:25:WiFi Association with 'STM' successful WIND (why specifically this?)
00118     
00119     wifi_callback.attach_us(Wifi_scheduler, 5000);//How low can we go?
00120         
00121     sync_wait_signal = false;
00122     status = wifi_init(&config);
00123     if(status!=WiFi_MODULE_SUCCESS)
00124     {
00125         return -1;
00126     }
00127     
00128     while(!sync_wait_signal)
00129     {
00130         if (timer.read_ms() > _timeout) {
00131             return -1;
00132         }
00133         __NOP();
00134     }
00135     
00136     return 0;
00137 }
00138 
00139 /**
00140 * @brief  network connect
00141           wrapper function for FW
00142 * @param  ssid: Access Point (AP) Name String  
00143 *         sec_key: Password String for AP
00144 *         priv_mode: type of security supported (FW mode)
00145 * @retval NSAPI Error Type
00146 */
00147 int SpwfSADevice::connect(char * ssid, char * sec_key, WiFi_Priv_Mode priv_mode) 
00148 {
00149     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00150     Timer timer;
00151     
00152     timer.start();
00153     sync_wait_signal = false;
00154     status = wifi_connect(ssid, sec_key, priv_mode);
00155     if(status!=WiFi_MODULE_SUCCESS)
00156     {
00157         return -1;
00158     }        
00159     
00160     while(!sync_wait_signal)
00161     {
00162         if (timer.read_ms() > _timeout) {
00163             return -1;
00164         }
00165         __NOP();
00166     } 
00167     
00168     return 0;
00169 }
00170 
00171 /**
00172 * @brief  network disconnect
00173           wrapper function for FW
00174 * @param  none
00175 * @retval error value
00176 */
00177 int SpwfSADevice::disconnect()
00178 {
00179     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00180 
00181     status = wifi_disconnect();//will set to Idle Mode
00182     if(status!=WiFi_MODULE_SUCCESS)
00183     {
00184         return -1;
00185     }
00186     
00187     return 0;
00188 }
00189 
00190 /** 
00191 * @brief  Get the local IP address
00192 *         wrapper function for FW
00193 * @param  none
00194 * @retval Null-terminated representation of the local IP address
00195 *         or null if not yet connected
00196 */
00197 const char *SpwfSADevice::getIPAddress()
00198 {
00199     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00200 
00201     status = WiFi_Get_IP_Address((uint8_t *)_ip_buffer);
00202     
00203     if(status!=WiFi_MODULE_SUCCESS)
00204     {
00205         return NULL;
00206     } else 
00207         return _ip_buffer;
00208 }
00209 
00210 /** 
00211 * @brief  Get the MAC address
00212 *         wrapper function for FW
00213 * @param  none
00214 * @retval Null-terminated representation of the MAC address
00215 *         or null if not yet connected
00216 */
00217 const char *SpwfSADevice::getMACAddress()
00218 {
00219     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00220 
00221     status = WiFi_Get_MAC_Address((uint8_t *)_mac_buffer);
00222     
00223     if(status!=WiFi_MODULE_SUCCESS)
00224     {
00225         return NULL;
00226     } else 
00227         return _mac_buffer;
00228 }
00229 
00230 /**
00231 * @brief  connect to a remote socket
00232 * @param  hostname: address of socket
00233           port_number: port number to connect
00234           protocol: TCP/UDP protocol
00235 *         sock_id: pointer to socket ID returned by FW
00236 * @retval error value
00237 */
00238 int SpwfSADevice::socket_client_open(uint8_t * hostname, uint32_t port_number, uint8_t * protocol, uint8_t * sock_id)
00239 {
00240     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00241 
00242     //Timeout of synchronous functions?
00243     status = wifi_socket_client_open(hostname, port_number, protocol, sock_id);
00244     if(status!=WiFi_MODULE_SUCCESS)
00245     {
00246         *sock_id = 99;//make sure socket id is not set(set to out of bounds of SPWFSA_SOCKET_COUNT range)
00247         return -1;
00248     }
00249     
00250     return 0;
00251 }
00252 
00253 /**
00254 * @brief  write to a remote socket
00255 * @param  sock_id: FW ID of the socket
00256           DataLength: size of the data
00257           pData: pointer to data
00258 * @retval error value
00259 */
00260 int SpwfSADevice::socket_client_write(uint8_t sock_id, uint16_t DataLength,char * pData)
00261 {
00262     int status=0;//number of bytes
00263 
00264     status = wifi_socket_client_write(sock_id, DataLength, pData);
00265     //map error to enum ns_error_t 
00266     
00267     if(status > 0)
00268     {
00269         return status;
00270     }
00271     return 0;
00272 }
00273 
00274 /**
00275 * @brief  receive from a remote socket
00276 * @param  sock_id: FW ID of the socket
00277           DataLength: size of the data
00278           pData: pointer to data
00279 * @retval error value
00280 */
00281 int SpwfSADevice::socket_client_recv(uint8_t sock_id, uint16_t RecvLength,char * pData)
00282 {
00283     static Timer recv_timer;
00284     //char debug_str[10];    
00285     static bool recv_call = true;
00286     
00287     if(recv_call)
00288     {
00289         //debug_print("\r\nrecv_call\r\n");
00290         //__disable_irq();
00291         wait_for_socket_data = false;
00292         recv_buff = (uint8_t*)pData;
00293         //__enable_irq();
00294         if(_timeout>0)
00295         recv_timer.start();
00296         recv_call = false;
00297         bytes_to_read = RecvLength;        
00298         bytes_read=0;
00299     }
00300             
00301     
00302     if(wait_for_socket_data || recv_timer.read_ms() >= _timeout)
00303     {      
00304         recv_call = true;
00305         _timeout = 0;
00306         wait_for_socket_data = true;
00307         recv_timer.stop();
00308         recv_timer.reset();
00309         wait_ms(1);
00310         if(bytes_read == 0) //<bytes_to_read?? 
00311             return -1;//return error if no bytes are read!
00312         else 
00313             return bytes_read;//return amount of data arrived so far
00314     }
00315     wait_ms(1); //CHECK:TODO: Need to wait to allow other IRQ's to run in case of non-blocking call?
00316     return -1;    
00317 }
00318 
00319 /**
00320 * @brief  scan the network
00321 * @param  scan_result: scan result data pointer
00322           max_scan_number: size of the scan result 
00323 * @retval error value
00324 */
00325 void SpwfSADevice::network_scan(wifi_scan *scan_result, uint16_t max_scan_number)
00326 {
00327     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00328     
00329     status = wifi_network_scan(scan_result, max_scan_number);
00330     if(status!=WiFi_MODULE_SUCCESS)
00331     {
00332         return;
00333     }
00334 }
00335 
00336 /**
00337 * @brief  HTTP GET from remote host
00338 * @param  hostname: address of remote host
00339           path: path to resource
00340           port_number: port number
00341 * @retval none
00342 */
00343 void SpwfSADevice::http_get(uint8_t * hostname, uint8_t * path, uint32_t port_number)
00344 {
00345     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00346     
00347     status = wifi_http_get((uint8_t *)hostname, (uint8_t *)path, port_number);
00348     if(status!=WiFi_MODULE_SUCCESS)
00349     {
00350         return;
00351     }    
00352 }
00353 
00354 /**
00355 * @brief  HTTP GET from remote host
00356 * @param  url_path: complete url of remote resource
00357 * @retval none
00358 */
00359 void SpwfSADevice::http_post(uint8_t * url_path)
00360 {
00361     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00362     
00363     status = wifi_http_post(url_path);
00364     if(status!=WiFi_MODULE_SUCCESS)
00365     {
00366         return;
00367     }    
00368 }
00369 
00370 /**
00371 * @brief  FW callback with data in socket
00372 * @param  sock_id: FW ID of the socket
00373           data_ptr: pointer to data from FW
00374           message_size: total data to arrive
00375           chunk_size: size of the data in this callback (<= message_size)
00376 * @retval none
00377 */
00378 void SpwfSADevice::signal_data_receive(uint8_t socket_id, uint8_t * data_ptr, uint32_t message_size, uint32_t chunk_size)
00379 {
00380     char debug_str[50];
00381     //Data will be copied or returned to user only if there is a pending request
00382     //Copy data to pData
00383     //sprintf((char*)debug_str,"sock_id: %d, size: %d, chunk: %d\r\n",socket_id, message_size, chunk_size); 
00384     //debug_print(debug_str);
00385             
00386     if(recv_buff && !wait_for_socket_data)
00387     {
00388         if((bytes_read + chunk_size)<= bytes_to_read)
00389         {
00390             memcpy(recv_buff + bytes_read, data_ptr, chunk_size);//only copy bytes_to_read asked by user//rest of the data is lost!!
00391             bytes_read += chunk_size;
00392         }
00393         else
00394             {
00395                 uint32_t x_size = (bytes_read + chunk_size) - bytes_to_read;
00396                 memcpy(recv_buff + bytes_read, data_ptr, chunk_size-x_size);
00397                 bytes_read += (chunk_size-x_size);
00398             }          
00399         
00400         if(bytes_read >= bytes_to_read)
00401         {
00402             __disable_irq();
00403             wait_for_socket_data = true;
00404             __enable_irq();
00405         }
00406     }
00407     else
00408     {
00409         debug_print("\r\n Socket:: Data Dropped: ");
00410         sprintf((char*)debug_str,"%d\r\n",chunk_size); 
00411         debug_print(debug_str);
00412         __disable_irq();
00413         wait_for_socket_data = true;
00414         __enable_irq();
00415     }
00416 }
00417 
00418 /**
00419 * @brief  synchronization function called from FW (used for connect,disconnect, ready, etc.)
00420 * @param  code: Status code value returned
00421 * @retval none
00422 */
00423 void SpwfSADevice::signal_synch_wait(WiFi_Status_t code)
00424 {
00425     if(code == WiFi_DISASSOCIATION)
00426     {
00427         //do nothing
00428     } 
00429     else
00430     {
00431         __disable_irq();
00432         sync_wait_signal = true;
00433         __enable_irq();
00434     }
00435 }
00436 
00437 /**
00438 * @brief  close a client socket
00439 * @param  sock_close_id: FW ID of the socket to close
00440 * @retval error value
00441 */
00442 int SpwfSADevice::socket_client_close(uint8_t sock_close_id)
00443 {
00444     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00445 
00446     status = wifi_socket_client_close(sock_close_id);
00447     //map error to enum ns_error_t 
00448     if(status!=WiFi_MODULE_SUCCESS)
00449     {
00450         return -1;
00451     }    
00452     
00453     return 0;
00454 }
00455 
00456 /**
00457 * @brief  open a server socket
00458 * @param  port_number: port number to listen on
00459 *         protocol: TCP/UDP protocol
00460 * @retval error value
00461 */
00462 int SpwfSADevice::socket_server_open(uint32_t port_number, uint8_t * protocol)
00463 {
00464     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00465 
00466     status = wifi_socket_server_open(port_number, protocol);
00467     //map error to enum ns_error_t 
00468     if(status!=WiFi_MODULE_SUCCESS)
00469     {
00470         return -1;
00471     }    
00472     
00473     return 0;
00474 }
00475 
00476 /**
00477 * @brief  write to a server socket
00478 * @param  data_length: size of the data
00479 *         pdata: pointer to data
00480 * @retval error value
00481 */
00482 int SpwfSADevice::socket_server_write(uint16_t data_length,char * pdata)
00483 {    
00484     int status = 0;//number of bytes
00485 
00486     status = wifi_socket_server_write(data_length, pdata);
00487     //map error to enum ns_error_t 
00488     if(status > 0)
00489     {
00490         return status;
00491     }
00492     return 0;
00493 }
00494 
00495 /**
00496 * @brief  close a server socket
00497 * @param  none (only one server socket supported)
00498 * @retval error value
00499 */
00500 int SpwfSADevice::socket_server_close(void)
00501 {    
00502     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00503 
00504     status = wifi_socket_server_close();
00505     //map error to enum ns_error_t 
00506     if(status!=WiFi_MODULE_SUCCESS)
00507     {
00508         return -1;
00509     }    
00510     
00511     return 0;
00512 }
00513 
00514 /**
00515 * @brief  attach/remove IRQ handler to UART
00516 * @param  attach: attach/remove boolean
00517 * @retval none
00518 */
00519 void SpwfSADevice::spwf_attach_irq(wifi_bool attach) 
00520 {
00521     if(attach)
00522     {
00523         uart_.attach(Rx_irq_handler, SerialBase::RxIrq);
00524     }
00525     else
00526     {
00527         uart_.attach(NULL, SerialBase::RxIrq);
00528     }
00529 }
00530 
00531 /**
00532 * @brief  write byte(s) to the UART
00533 * @param  cmd: pointer to data
00534 *         size: size of data
00535 * @retval error value
00536 */
00537 int SpwfSADevice::spwf_send(const char * cmd, uint16_t size) 
00538 {
00539     Timer timer;
00540     int i, bytes;
00541     //timer.start();
00542     
00543     //uart_.puts(cmd);//string may contain '\0' character in between hence not used
00544     
00545     for(i=0;i<size;i++)
00546     {
00547         uart_.putc(cmd[i]);        
00548         //if (timer.read_ms() > _timeout) {
00549             //return -1;
00550         //}
00551     }
00552     
00553     bytes = (int) size - 2;//we send 2 bytes extra for module
00554     return bytes;
00555 }
00556 
00557 /**
00558 * @brief  read a byte from the UART
00559 * @param  none
00560 * @retval byte character
00561 */
00562 char SpwfSADevice::spwf_get(void) 
00563 {
00564     return(uart_.getc());
00565 }
00566 
00567 /**
00568 * @brief  (re)set the SPWF wakeup GPIO pin
00569 * @param  wake (re)set value
00570 * @retval none
00571 */
00572 void SpwfSADevice::spwf_wakeup(int wake)
00573 {
00574     wakeup_.write(wake);
00575 }
00576 
00577 /**
00578 * @brief  (re)set the SPWF reset GPIO pin
00579 * @param  reset (re)set value
00580 * @retval none
00581 */
00582 void SpwfSADevice::spwf_reset(int reset)
00583 {
00584     rst_.write(reset);
00585 }
00586 
00587 /**
00588 * @brief  (re)set the SPWF RTS GPIO line
00589 * @param  rts (re)set value
00590 * @retval none
00591 */
00592 void SpwfSADevice::spwf_rts(int rts)
00593 {
00594     rts_.write(rts);
00595 }
00596 
00597 /**
00598 * @brief  read the SPWF RTS GPIO pin
00599 * @param  none
00600 * @retval none
00601 */
00602 int SpwfSADevice::spwf_read_rts()
00603 {
00604     return(rts_.read());
00605 }
00606 
00607 /**
00608 * @brief  send debug print to serial terminal
00609 * @param  string: data for debug print
00610 * @retval none
00611 */
00612 void SpwfSADevice::debug_print(const char * string)
00613 {
00614     term_.puts(string);
00615 }
00616 
00617 /**
00618 * @brief  (re)set the switch for incoming client (server socket)
00619 * @param  set: boolean to (re)set
00620 * @retval none
00621 */
00622 void SpwfSADevice::set_wait_for_incoming_client(bool set)
00623 {
00624     wait_for_incoming_client = set;    
00625 }
00626 
00627 /**
00628 * @brief  get the switch for incoming client (server socket)
00629 * @param  none
00630 * @retval boolean
00631 */
00632 bool SpwfSADevice::get_wait_for_incoming_client()
00633 {
00634     return wait_for_incoming_client;
00635 }
00636