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: cc3000_ping_demo_try_2
Fork of cc3000_hostdriver_mbedsocket by
cc3000_spi.cpp
00001 /***************************************************************************** 00002 * 00003 * C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to 00004 * Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and 00005 * provided help. 00006 * 00007 * This version of "host driver" uses CC3000 Host Driver Implementation. Thus 00008 * read the following copyright: 00009 * 00010 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions 00014 * are met: 00015 * 00016 * Redistributions of source code must retain the above copyright 00017 * notice, this list of conditions and the following disclaimer. 00018 * 00019 * Redistributions in binary form must reproduce the above copyright 00020 * notice, this list of conditions and the following disclaimer in the 00021 * documentation and/or other materials provided with the 00022 * distribution. 00023 * 00024 * Neither the name of Texas Instruments Incorporated nor the names of 00025 * its contributors may be used to endorse or promote products derived 00026 * from this software without specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00029 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00030 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00031 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00032 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00033 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00034 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00035 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00036 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00037 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00038 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00039 * 00040 *****************************************************************************/ 00041 #include "cc3000.h" 00042 #include "cc3000_spi.h" 00043 00044 namespace mbed_cc3000 { 00045 00046 cc3000_spi::cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, cc3000_event &event, cc3000_simple_link &simple_link) 00047 : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _event(event), _simple_link(simple_link) { 00048 00049 _wlan_spi.format(8,1); 00050 _wlan_spi.frequency(12000000); 00051 _wlan_irq.fall(this, &cc3000_spi::WLAN_IRQHandler); 00052 00053 _wlan_en = 0; 00054 _wlan_cs = 1; 00055 wait_ms(50); /* mbed board delay */ 00056 } 00057 00058 cc3000_spi::~cc3000_spi() { 00059 00060 } 00061 00062 void cc3000_spi::wlan_irq_enable() 00063 { 00064 _process_irq = true; 00065 //_wlan_irq.enable_irq(); 00066 00067 if (wlan_irq_read() == 0) { 00068 WLAN_IRQHandler(); 00069 } 00070 } 00071 00072 void cc3000_spi::wlan_irq_disable() { 00073 _process_irq = false; 00074 //_wlan_irq.disable_irq(); 00075 } 00076 00077 uint32_t cc3000_spi::wlan_irq_read() { 00078 return _wlan_irq.read(); 00079 } 00080 00081 void cc3000_spi::close() { 00082 wlan_irq_disable(); 00083 } 00084 00085 void cc3000_spi::open() { 00086 _spi_info.spi_state = eSPI_STATE_POWERUP; 00087 _spi_info.tx_packet_length = 0; 00088 _spi_info.rx_packet_length = 0; 00089 wlan_irq_enable(); 00090 } 00091 00092 uint32_t cc3000_spi::first_write(uint8_t *buffer, uint16_t length) { 00093 _wlan_cs = 0; 00094 wait_us(50); 00095 00096 /* first 4 bytes of the data */ 00097 write_synchronous(buffer, 4); 00098 wait_us(50); 00099 write_synchronous(buffer + 4, length - 4); 00100 _spi_info.spi_state = eSPI_STATE_IDLE; 00101 _wlan_cs = 1; 00102 00103 return 0; 00104 } 00105 00106 00107 uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) { 00108 uint8_t pad = 0; 00109 // check the total length of the packet in order to figure out if padding is necessary 00110 if(!(length & 0x0001)) { 00111 pad++; 00112 } 00113 buffer[0] = WRITE; 00114 buffer[1] = HI(length + pad); 00115 buffer[2] = LO(length + pad); 00116 buffer[3] = 0; 00117 buffer[4] = 0; 00118 00119 length += (SPI_HEADER_SIZE + pad); 00120 00121 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) 00122 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! 00123 uint8_t *transmit_buffer = _simple_link.get_transmit_buffer(); 00124 if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00125 while (1); 00126 } 00127 00128 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00129 while (_spi_info.spi_state != eSPI_STATE_INITIALIZED); 00130 } 00131 00132 if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) { 00133 // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command 00134 first_write(buffer, length); 00135 } else { 00136 // Prevent occurence of a race condition when 2 back to back packets are sent to the 00137 // device, so the state will move to IDLE and once again to not IDLE due to IRQ 00138 wlan_irq_disable(); 00139 00140 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00141 00142 _spi_info.spi_state = eSPI_STATE_WRITE_IRQ; 00143 //_spi_info.pTxPacket = buffer; 00144 _spi_info.tx_packet_length = length; 00145 00146 // Assert the CS line and wait until the IRQ line is active, then initialize the write operation 00147 _wlan_cs = 0; 00148 00149 wlan_irq_enable(); 00150 } 00151 00152 // Wait until the transaction ends 00153 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00154 00155 return 0; 00156 } 00157 00158 void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) { 00159 while(size) { 00160 _wlan_spi.write(*data++); 00161 size--; 00162 } 00163 } 00164 00165 void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) { 00166 for (uint32_t i = 0; i < size; i++) { 00167 data[i] = _wlan_spi.write(0x03); 00168 } 00169 } 00170 00171 uint32_t cc3000_spi::read_data_cont() { 00172 int32_t data_to_recv; 00173 uint8_t *evnt_buff, type; 00174 00175 //determine the packet type 00176 evnt_buff = _simple_link.get_received_buffer(); 00177 data_to_recv = 0; 00178 STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); 00179 00180 switch(type) { 00181 case HCI_TYPE_DATA: 00182 // Read the remaining data.. 00183 STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); 00184 if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { 00185 data_to_recv++; 00186 } 00187 00188 if (data_to_recv) { 00189 read_synchronous(evnt_buff + 10, data_to_recv); 00190 } 00191 break; 00192 case HCI_TYPE_EVNT: 00193 // Calculate the rest length of the data 00194 STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); 00195 data_to_recv -= 1; 00196 // Add padding byte if needed 00197 if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { 00198 data_to_recv++; 00199 } 00200 00201 if (data_to_recv) { 00202 read_synchronous(evnt_buff + 10, data_to_recv); 00203 } 00204 00205 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00206 break; 00207 } 00208 return 0; 00209 } 00210 00211 void cc3000_spi::set_wlan_en(uint8_t value) { 00212 if (value) { 00213 _wlan_en = 1; 00214 } else { 00215 _wlan_en = 0; 00216 } 00217 } 00218 00219 void cc3000_spi::WLAN_IRQHandler() { 00220 if (_process_irq) { 00221 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00222 // Inform HCI Layer that IRQ occured after powerup 00223 _spi_info.spi_state = eSPI_STATE_INITIALIZED; 00224 } else if (_spi_info.spi_state == eSPI_STATE_IDLE) { 00225 _spi_info.spi_state = eSPI_STATE_READ_IRQ; 00226 /* IRQ line goes low - acknowledge it */ 00227 _wlan_cs = 0; 00228 read_synchronous(_simple_link.get_received_buffer(), 10); 00229 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00230 00231 // The header was read - continue with the payload read 00232 if (!read_data_cont()) { 00233 // All the data was read - finalize handling by switching to the task 00234 // Trigger Rx processing 00235 wlan_irq_disable(); 00236 _wlan_cs = 1; 00237 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) 00238 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! 00239 uint8_t *received_buffer = _simple_link.get_received_buffer(); 00240 if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00241 while (1); 00242 } 00243 00244 _spi_info.spi_state = eSPI_STATE_IDLE; 00245 _event.received_handler(received_buffer + SPI_HEADER_SIZE); 00246 } 00247 } else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) { 00248 write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length); 00249 _spi_info.spi_state = eSPI_STATE_IDLE; 00250 _wlan_cs = 1; 00251 } 00252 } 00253 } 00254 00255 } // namespace mbed_cc3000
Generated on Tue Jul 12 2022 18:37:32 by
