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.
Dependencies: MaximInterface
CC3100.cpp
00001 /******************************************************************************* 00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 *******************************************************************************/ 00032 00033 #include <cstdio> 00034 #include <cstring> 00035 #include <simplelink.h> 00036 #include <mbed-os/drivers/InterruptIn.h> 00037 #include <mbed-os/platform/mbed_wait_api.h> 00038 #include "CC3100.hpp" 00039 00040 using std::printf; 00041 using std::strlen; 00042 00043 static CC3100::State currentState = CC3100::Stopped; 00044 00045 static mbed::InterruptIn irq(MBED_CONF_APP_CC3100_INTR_PIN); 00046 static mbed::DigitalOut nHIB(MBED_CONF_APP_CC3100_NHIB_PIN, 0); 00047 00048 static SL_P_EVENT_HANDLER pIrqEventHandler = NULL; 00049 static void * pIrqEventHandlerValue = NULL; 00050 00051 _SlFd_t sl_IfOpen(const char * ifName, unsigned long flags) { 00052 _SlFd_t fd = NULL; 00053 if (ifName) { 00054 std::sscanf(ifName, "%p", &fd); 00055 } 00056 return fd; 00057 } 00058 00059 int sl_IfClose(_SlFd_t fd) { 00060 return 0; // Success 00061 } 00062 00063 int sl_IfRead(_SlFd_t fd, unsigned char * pBuff, int len) { 00064 if (!fd) { 00065 return 0; // Failure 00066 } 00067 std::memset(pBuff, 0xFF, len); 00068 static_cast<CC3100::SPI *>(fd)->transfer(pBuff, len, pBuff); 00069 return len; // Success 00070 } 00071 00072 int sl_IfWrite(_SlFd_t fd, const unsigned char * pBuff, int len) { 00073 if (!fd) { 00074 return 0; // Failure 00075 } 00076 static_cast<CC3100::SPI *>(fd)->transfer(pBuff, len, NULL); 00077 return len; // Success 00078 } 00079 00080 int sl_IfRegIntHdlr(SL_P_EVENT_HANDLER InterruptHdl, void * pValue) { 00081 pIrqEventHandler = InterruptHdl; 00082 pIrqEventHandlerValue = pValue; 00083 return 0; // Success 00084 } 00085 00086 static void interruptHandler(void) { 00087 if (pIrqEventHandler) { 00088 pIrqEventHandler(pIrqEventHandlerValue); 00089 } 00090 } 00091 00092 void sl_DeviceEnable(void) { 00093 irq.rise(&interruptHandler); 00094 nHIB = 1; 00095 } 00096 00097 void sl_DeviceDisable(void) { 00098 irq.rise(NULL); 00099 nHIB = 0; 00100 } 00101 00102 /*! 00103 \brief This function handles general error events indication 00104 00105 \param[in] pDevEvent is the event passed to the handler 00106 00107 \return None 00108 */ 00109 void SimpleLinkGeneralEventHandler(SlDeviceEvent_t * pDevEvent) { 00110 /* 00111 * Most of the general errors are not FATAL are are to be handled 00112 * appropriately by the application 00113 */ 00114 printf(" [GENERAL EVENT] \n\r"); 00115 } 00116 00117 /*! 00118 \brief This function handles WLAN events 00119 00120 \param[in] pWlanEvent is the event passed to the handler 00121 00122 \return None 00123 00124 \note 00125 00126 \warning 00127 */ 00128 void SimpleLinkWlanEventHandler(SlWlanEvent_t * pWlanEvent) { 00129 if (!pWlanEvent) { 00130 printf(" [WLAN EVENT] NULL Pointer Error \n\r"); 00131 return; 00132 } 00133 00134 switch (pWlanEvent->Event) { 00135 case SL_WLAN_CONNECT_EVENT: 00136 currentState = CC3100::Connected; 00137 00138 /* 00139 * Information about the connected AP (like name, MAC etc) will be 00140 * available in 'slWlanConnectAsyncResponse_t' - Applications 00141 * can use it if required 00142 * 00143 * slWlanConnectAsyncResponse_t *pEventData = NULL; 00144 * pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected; 00145 * 00146 */ 00147 break; 00148 00149 case SL_WLAN_DISCONNECT_EVENT: { 00150 currentState = CC3100::Disconnected; 00151 00152 slWlanConnectAsyncResponse_t & pEventData = 00153 pWlanEvent->EventData.STAandP2PModeDisconnected; 00154 00155 /* If the user has initiated 'Disconnect' request, 'reason_code' is SL_USER_INITIATED_DISCONNECTION */ 00156 if (SL_WLAN_DISCONNECT_USER_INITIATED_DISCONNECTION == 00157 pEventData.reason_code) { 00158 printf(" Device disconnected from the AP on application's request \n\r"); 00159 } else { 00160 printf(" Device disconnected from the AP on an ERROR..!! \n\r"); 00161 } 00162 } break; 00163 00164 default: 00165 printf(" [WLAN EVENT] Unexpected event \n\r"); 00166 break; 00167 } 00168 } 00169 00170 /*! 00171 \brief This function handles events for IP address acquisition via DHCP 00172 indication 00173 00174 \param[in] pNetAppEvent is the event passed to the handler 00175 00176 \return None 00177 00178 \note 00179 00180 \warning 00181 */ 00182 void SimpleLinkNetAppEventHandler(SlNetAppEvent_t * pNetAppEvent) { 00183 if (!pNetAppEvent) { 00184 printf(" [NETAPP EVENT] NULL Pointer Error \n\r"); 00185 return; 00186 } 00187 00188 switch (pNetAppEvent->Event) { 00189 case SL_NETAPP_IPV4_IPACQUIRED_EVENT: 00190 currentState = CC3100::Connected; 00191 00192 //SlIpV4AcquiredAsync_t & pEventData = pNetAppEvent->EventData.ipAcquiredV4; 00193 break; 00194 00195 default: 00196 printf(" [NETAPP EVENT] Unexpected event \n\r"); 00197 break; 00198 } 00199 } 00200 00201 /*! 00202 \brief This function handles socket events indication 00203 00204 \param[in] pSock is the event passed to the handler 00205 00206 \return None 00207 */ 00208 void SimpleLinkSockEventHandler(SlSockEvent_t * pSock) { 00209 if (!pSock) { 00210 printf(" [SOCK EVENT] NULL Pointer Error \n\r"); 00211 return; 00212 } 00213 00214 switch (pSock->Event) { 00215 case SL_SOCKET_TX_FAILED_EVENT: 00216 /* 00217 * TX Failed 00218 * 00219 * Information about the socket descriptor and status will be 00220 * available in 'SlSockEventData_t' - Applications can use it if 00221 * required 00222 * 00223 * SlSockEventData_u *pEventData = NULL; 00224 * pEventData = & pSock->socketAsyncEvent; 00225 */ 00226 switch (pSock->socketAsyncEvent.SockTxFailData.status) { 00227 case SL_ECLOSE: 00228 printf(" [SOCK EVENT] Close socket operation failed to transmit all " 00229 "queued packets\n\r"); 00230 break; 00231 00232 default: 00233 printf(" [SOCK EVENT] Unexpected event \n\r"); 00234 break; 00235 } 00236 break; 00237 00238 default: 00239 printf(" [SOCK EVENT] Unexpected event \n\r"); 00240 break; 00241 } 00242 } 00243 00244 /*! 00245 \brief This function handles ping report events 00246 00247 \param[in] pPingReport holds the ping report statistics 00248 00249 \return None 00250 00251 \note 00252 00253 \warning 00254 */ 00255 static void SimpleLinkPingReport(SlPingReport_t * pPingReport) { 00256 currentState = CC3100::Connected; 00257 00258 if (!pPingReport) { 00259 printf(" [PING REPORT] NULL Pointer Error\r\n"); 00260 return; 00261 } 00262 00263 printf(" [PING REPORT] Sent: %lu, Received: %lu\r\n", 00264 pPingReport->PacketsSent, pPingReport->PacketsReceived); 00265 } 00266 00267 CC3100::SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) 00268 : spi(mosi, miso, sclk), cs(ssel, 1) {} 00269 00270 void CC3100::SPI::transfer(const uint8_t * txData, size_t dataSize, 00271 uint8_t * rxData) { 00272 const int cs_delay_ms = 5; 00273 00274 cs = 0; 00275 wait_ms(cs_delay_ms); 00276 for (size_t i = 0; i < dataSize; ++i) { 00277 if (rxData) { 00278 rxData[i] = spi.write(txData[i]); 00279 } else { 00280 spi.write(txData[i]); 00281 } 00282 } 00283 wait_ms(cs_delay_ms); 00284 cs = 1; 00285 } 00286 00287 CC3100::CC3100() 00288 : spi(MBED_CONF_APP_CC3100_MOSI_PIN, MBED_CONF_APP_CC3100_MISO_PIN, 00289 MBED_CONF_APP_CC3100_CLK_PIN, MBED_CONF_APP_CC3100_NCS_PIN) {} 00290 00291 CC3100 & CC3100::instance() { 00292 static CC3100 instance; 00293 return instance; 00294 } 00295 00296 int CC3100::start() { 00297 // Adapter should be stopped. 00298 if (currentState != Stopped) { 00299 return invalidState; 00300 } 00301 00302 const int result = sl_Start(&spi, NULL, NULL); 00303 if (result >= 0) { 00304 currentState = Disconnected; 00305 } 00306 return result; 00307 } 00308 00309 CC3100::State CC3100::state() const { return currentState; } 00310 00311 int CC3100::stop() { 00312 // Adapter should not be stopped. 00313 if (currentState == Stopped) { 00314 return invalidState; 00315 } 00316 00317 const int result = sl_Stop(0xFF); 00318 if (result >= 0) { 00319 currentState = Stopped; 00320 } 00321 return result; 00322 } 00323 00324 void CC3100::update() { sl_Task(); } 00325 00326 int CC3100::setDateTime(const std::tm & dateTime) { 00327 const SlDateTime_t slDateTime = { 00328 static_cast<_u32>(dateTime.tm_sec), // sl_tm_sec 00329 static_cast<_u32>(dateTime.tm_min), // sl_tm_min 00330 static_cast<_u32>(dateTime.tm_hour), // sl_tm_hour 00331 static_cast<_u32>(dateTime.tm_mday), // sl_tm_day 00332 static_cast<_u32>(dateTime.tm_mon), // sl_tm_mon 00333 static_cast<_u32>(dateTime.tm_year) // sl_tm_year 00334 }; 00335 return sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, 00336 SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, 00337 sizeof(SlDateTime_t), 00338 reinterpret_cast<const _u8 *>(&slDateTime)); 00339 } 00340 00341 int CC3100::set_credentials(const char * ssid, const char * pass, 00342 nsapi_security_t security) { 00343 this->ssid.assign(ssid); 00344 this->pass.assign(pass); 00345 this->security = security; 00346 return 0; 00347 } 00348 00349 int CC3100::connect(const char * ssid, const char * pass, 00350 nsapi_security_t security, uint8_t channel) { 00351 // Adapter should be disconnected. 00352 if (currentState != Disconnected) { 00353 return invalidState; 00354 } 00355 00356 SlSecParams_t secParams = { 00357 SL_SEC_TYPE_OPEN, // Type 00358 const_cast<_i8 *>(reinterpret_cast<const _i8 *>(pass)), // Key 00359 static_cast<_u8>(strlen(pass)), // KeyLen 00360 }; 00361 switch (security) { 00362 case NSAPI_SECURITY_WPA2: 00363 case NSAPI_SECURITY_WPA: 00364 case NSAPI_SECURITY_WPA_WPA2: 00365 secParams.Type = SL_SEC_TYPE_WPA_WPA2; 00366 break; 00367 00368 case NSAPI_SECURITY_WEP: 00369 secParams.Type = SL_SEC_TYPE_WEP; 00370 break; 00371 00372 case NSAPI_SECURITY_NONE: 00373 case NSAPI_SECURITY_UNKNOWN: 00374 secParams.Type = SL_SEC_TYPE_OPEN; 00375 break; 00376 00377 default: 00378 return invalidState; 00379 } 00380 int result = sl_WlanConnect(reinterpret_cast<const _i8 *>(ssid), strlen(ssid), 00381 NULL, &secParams, NULL); 00382 if (result == SL_RET_CODE_OK) { 00383 // Wait for completion. 00384 int attempts = 1000; 00385 do { 00386 wait_ms(10); 00387 update(); 00388 } while ((currentState != Connected) && (--attempts > 0)); 00389 if (attempts == 0) { 00390 result = SL_RET_CODE_ABORT; 00391 } 00392 } 00393 return result; 00394 } 00395 00396 int CC3100::connect(const char * ssid, const char * username, 00397 const char * password) { 00398 // Adapter should be disconnected. 00399 if (currentState != Disconnected) { 00400 return invalidState; 00401 } 00402 00403 uint8_t values = 0; 00404 sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, 19, 1, &values); 00405 00406 SlSecParams_t secParams = { 00407 SL_SEC_TYPE_WPA_ENT, // Type 00408 const_cast<_i8 *>(reinterpret_cast<const _i8 *>(password)), // Key 00409 static_cast<_u8>(strlen(password)) // KeyLen 00410 }; 00411 SlSecParamsExt_t secParamsExt = { 00412 const_cast<_i8 *>(reinterpret_cast<const _i8 *>(username)), // User 00413 static_cast<_u8>(strlen(username)), // UserLen 00414 NULL, // AnonUser 00415 0, // AnonUserLen 00416 0, // CertIndex 00417 SL_ENT_EAP_METHOD_PEAP0_MSCHAPv2 // EapMethod 00418 }; 00419 int result = sl_WlanConnect(reinterpret_cast<const _i8 *>(ssid), strlen(ssid), 00420 NULL, &secParams, &secParamsExt); 00421 if (result == SL_RET_CODE_OK) { 00422 // Wait for completion. 00423 int attempts = 1000; 00424 do { 00425 wait_ms(10); 00426 update(); 00427 } while ((currentState != Connected) && (--attempts > 0)); 00428 if (attempts == 0) { 00429 result = SL_RET_CODE_ABORT; 00430 } 00431 } 00432 return result; 00433 } 00434 00435 int CC3100::disconnect() { 00436 // Adapter should be connected. 00437 if (currentState != Connected) { 00438 return invalidState; 00439 } 00440 00441 return sl_WlanDisconnect(); 00442 } 00443 00444 int CC3100::gethostbyname(const char * host, SocketAddress * address, 00445 nsapi_version_t version) { 00446 // TODO: Add IPv6 support 00447 00448 // Adapter should be connected. 00449 if (currentState != Connected) { 00450 return invalidState; 00451 } 00452 00453 uint32_t addressInt; 00454 int result; 00455 int attempts = 1000; 00456 // Wait for DNS servers. 00457 do { 00458 wait_ms(10); 00459 result = sl_NetAppDnsGetHostByName( 00460 const_cast<_i8 *>(reinterpret_cast<const _i8 *>(host)), strlen(host), 00461 reinterpret_cast<_u32 *>(&addressInt), SL_AF_INET); 00462 } while ((result == SL_NET_APP_DNS_NO_SERVER) && (--attempts > 0)); 00463 if (result == SL_RET_CODE_OK) { 00464 nsapi_addr_t addressBytes = { 00465 NSAPI_IPv4, // version 00466 0, // bytes 00467 }; 00468 for (int i = 4; i > 0; --i) { 00469 addressBytes.bytes[i - 1] = addressInt; 00470 addressInt >>= 8; 00471 } 00472 address->set_addr(addressBytes); 00473 } 00474 return result; 00475 } 00476 00477 int CC3100::ping(const SocketAddress & address) { 00478 // Adapter should be connected. 00479 if (currentState != Connected) { 00480 return invalidState; 00481 } 00482 00483 SlPingStartCommand_t pingParams = { 00484 1000, // PingIntervalTime 00485 20, // PingSize 00486 3000, // PingRequestTimeout 00487 3, // TotalNumberOfAttempts 00488 0, // Flags 00489 0 // Ip 00490 }; 00491 for (int i = 0; i < 4; ++i) { 00492 pingParams.Ip <<= 8; 00493 pingParams.Ip |= address.get_addr().bytes[i]; 00494 } 00495 SlPingReport_t pingReport; 00496 int result = sl_NetAppPingStart( 00497 (SlPingStartCommand_t *)&pingParams, SL_AF_INET, 00498 static_cast<SlPingReport_t *>(&pingReport), SimpleLinkPingReport); 00499 if (result == SL_RET_CODE_OK) { 00500 // Wait for completion. 00501 currentState = Pinging; 00502 int attempts = 1000; 00503 do { 00504 wait_ms(10); 00505 update(); 00506 } while ((currentState == Pinging) && (--attempts > 0)); 00507 if (attempts == 0) { 00508 result = SL_RET_CODE_ABORT; 00509 } 00510 } 00511 return result; 00512 } 00513 00514 int CC3100::socket_open(nsapi_socket_t * handle, nsapi_protocol_t proto) { 00515 int16_t result; 00516 switch (proto) { 00517 case NSAPI_TCP: 00518 result = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, 0); 00519 break; 00520 00521 case NSAPI_UDP: 00522 result = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0); 00523 break; 00524 00525 /*case SL_SEC_SOCKET: 00526 result = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET); 00527 break;*/ 00528 00529 default: 00530 result = SL_SOC_ERROR; 00531 break; 00532 } 00533 if (result >= 0) { 00534 *handle = new int16_t(result); 00535 00536 // Set non-blocking. 00537 SlSockNonblocking_t enableOption = { 00538 1 // NonblockingEnabled 00539 }; 00540 result = sl_SetSockOpt( 00541 *static_cast<int16_t *>(*handle), SL_SOL_SOCKET, SL_SO_NONBLOCKING, 00542 reinterpret_cast<_u8 *>(&enableOption), sizeof(enableOption)); 00543 00544 if (result < 0) { 00545 socket_close(*handle); 00546 } 00547 } 00548 return result; 00549 } 00550 00551 int CC3100::socket_set_cert_path(nsapi_socket_t handle, const char * certPath) { 00552 // Set CA certificate. 00553 return sl_SetSockOpt(*static_cast<int16_t *>(handle), SL_SOL_SOCKET, 00554 SL_SO_SECURE_FILES_CA_FILE_NAME, certPath, 00555 strlen(certPath)); 00556 } 00557 00558 int CC3100::socket_close(nsapi_socket_t handle) { 00559 int16_t * castedHandle = static_cast<int16_t *>(handle); 00560 const int result = sl_Close(*castedHandle); 00561 delete castedHandle; 00562 return result; 00563 } 00564 00565 int CC3100::socket_bind(nsapi_socket_t handle, const SocketAddress & address) { 00566 // TODO: Add IPv6 support 00567 if (address.get_addr().version != NSAPI_IPv4) { 00568 return SL_SOC_ERROR; 00569 } 00570 00571 SlSockAddrIn_t localAddr = {AF_INET, // sin_family 00572 sl_Htons(address.get_port()), // sin_port 00573 { // sin_addr 00574 0 // s_addr 00575 }}; 00576 for (int i = 4; i > 0; --i) { 00577 localAddr.sin_addr.s_addr <<= 8; 00578 localAddr.sin_addr.s_addr |= address.get_addr().bytes[i - 1]; 00579 } 00580 return sl_Bind(*static_cast<int16_t *>(handle), 00581 reinterpret_cast<SlSockAddr_t *>(&localAddr), 00582 sizeof(localAddr)); 00583 } 00584 00585 int CC3100::socket_listen(nsapi_socket_t handle, int backlog) { 00586 return sl_Listen(*static_cast<int16_t *>(handle), backlog); 00587 } 00588 00589 int CC3100::socket_connect(nsapi_socket_t handle, 00590 const SocketAddress & address) { 00591 // TODO: Add IPv6 support 00592 if (address.get_addr().version != NSAPI_IPv4) { 00593 return SL_SOC_ERROR; 00594 } 00595 00596 SlSockAddrIn_t addr = {AF_INET, // sin_family 00597 sl_Htons(address.get_port()), // sin_port 00598 { // sin_addr 00599 0 // s_addr 00600 }}; 00601 for (int i = 4; i > 0; --i) { 00602 addr.sin_addr.s_addr <<= 8; 00603 addr.sin_addr.s_addr |= address.get_addr().bytes[i - 1]; 00604 } 00605 int result; 00606 int attempts = 1000; 00607 do { 00608 wait_ms(10); 00609 result = sl_Connect(*static_cast<int16_t *>(handle), 00610 reinterpret_cast<SlSockAddr_t *>(&addr), sizeof(addr)); 00611 } while ((result == SL_EALREADY) && (--attempts > 0)); 00612 if (result > 0) { 00613 result = 0; 00614 } 00615 return result; 00616 } 00617 00618 int CC3100::socket_send(nsapi_socket_t handle, const void * data, 00619 unsigned size) { 00620 return sl_Send(*static_cast<int16_t *>(handle), data, size, 0); 00621 } 00622 00623 int CC3100::socket_recv(nsapi_socket_t handle, void * data, unsigned size) { 00624 int result = sl_Recv(*static_cast<int16_t *>(handle), data, size, 0); 00625 if (result == SL_EAGAIN) { 00626 result = NSAPI_ERROR_WOULD_BLOCK; 00627 } 00628 return result; 00629 }
Generated on Tue Jul 12 2022 12:06:48 by
1.7.2