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.
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, Mutex & mutex, 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), _mutex(mutex), _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 _mutex.lock(); 00094 _wlan_cs = 0; 00095 wait_us(50); 00096 00097 /* first 4 bytes of the data */ 00098 write_synchronous(buffer, 4); 00099 wait_us(50); 00100 write_synchronous(buffer + 4, length - 4); 00101 _spi_info.spi_state = eSPI_STATE_IDLE; 00102 _wlan_cs = 1; 00103 _mutex.unlock(); 00104 00105 return 0; 00106 } 00107 00108 00109 uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) { 00110 uint8_t pad = 0; 00111 // check the total length of the packet in order to figure out if padding is necessary 00112 if(!(length & 0x0001)) { 00113 pad++; 00114 } 00115 buffer[0] = WRITE; 00116 buffer[1] = HI(length + pad); 00117 buffer[2] = LO(length + pad); 00118 buffer[3] = 0; 00119 buffer[4] = 0; 00120 00121 length += (SPI_HEADER_SIZE + pad); 00122 00123 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) 00124 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! 00125 uint8_t *transmit_buffer = _simple_link.get_transmit_buffer(); 00126 if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00127 while (1); 00128 } 00129 00130 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00131 while (_spi_info.spi_state != eSPI_STATE_INITIALIZED); 00132 } 00133 00134 if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) { 00135 // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command 00136 first_write(buffer, length); 00137 } else { 00138 // Prevent occurence of a race condition when 2 back to back packets are sent to the 00139 // device, so the state will move to IDLE and once again to not IDLE due to IRQ 00140 wlan_irq_disable(); 00141 00142 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00143 00144 _spi_info.spi_state = eSPI_STATE_WRITE_IRQ; 00145 //_spi_info.pTxPacket = buffer; 00146 _spi_info.tx_packet_length = length; 00147 00148 // Assert the CS line and wait until the IRQ line is active, then initialize the write operation 00149 _mutex.lock(); 00150 _wlan_cs = 0; 00151 00152 wlan_irq_enable(); 00153 } 00154 00155 // Wait until the transaction ends 00156 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00157 00158 return 0; 00159 } 00160 00161 void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) { 00162 while(size) { 00163 _wlan_spi.write(*data++); 00164 size--; 00165 } 00166 } 00167 00168 void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) { 00169 for (uint32_t i = 0; i < size; i++) { 00170 data[i] = _wlan_spi.write(0x03); 00171 } 00172 } 00173 00174 uint32_t cc3000_spi::read_data_cont() { 00175 int32_t data_to_recv; 00176 uint8_t *evnt_buff, type; 00177 00178 //determine the packet type 00179 evnt_buff = _simple_link.get_received_buffer(); 00180 data_to_recv = 0; 00181 STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); 00182 00183 switch(type) { 00184 case HCI_TYPE_DATA: 00185 // Read the remaining data.. 00186 STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); 00187 if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { 00188 data_to_recv++; 00189 } 00190 00191 if (data_to_recv) { 00192 read_synchronous(evnt_buff + 10, data_to_recv); 00193 } 00194 break; 00195 case HCI_TYPE_EVNT: 00196 // Calculate the rest length of the data 00197 STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); 00198 data_to_recv -= 1; 00199 // Add padding byte if needed 00200 if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { 00201 data_to_recv++; 00202 } 00203 00204 if (data_to_recv) { 00205 read_synchronous(evnt_buff + 10, data_to_recv); 00206 } 00207 00208 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00209 break; 00210 } 00211 return 0; 00212 } 00213 00214 void cc3000_spi::set_wlan_en(uint8_t value) { 00215 if (value) { 00216 _wlan_en = 1; 00217 } else { 00218 _wlan_en = 0; 00219 } 00220 } 00221 00222 void cc3000_spi::WLAN_IRQHandler() { 00223 if (_process_irq) { 00224 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00225 // Inform HCI Layer that IRQ occured after powerup 00226 _spi_info.spi_state = eSPI_STATE_INITIALIZED; 00227 } else if (_spi_info.spi_state == eSPI_STATE_IDLE) { 00228 _spi_info.spi_state = eSPI_STATE_READ_IRQ; 00229 /* IRQ line goes low - acknowledge it */ 00230 _mutex.lock(); 00231 _wlan_cs = 0; 00232 read_synchronous(_simple_link.get_received_buffer(), 10); 00233 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00234 00235 // The header was read - continue with the payload read 00236 if (!read_data_cont()) { 00237 // All the data was read - finalize handling by switching to the task 00238 // Trigger Rx processing 00239 wlan_irq_disable(); 00240 _wlan_cs = 1; 00241 _mutex.unlock(); 00242 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) 00243 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! 00244 uint8_t *received_buffer = _simple_link.get_received_buffer(); 00245 if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00246 while (1); 00247 } 00248 00249 _spi_info.spi_state = eSPI_STATE_IDLE; 00250 _event.received_handler(received_buffer + SPI_HEADER_SIZE); 00251 } 00252 } else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) { 00253 write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length); 00254 _spi_info.spi_state = eSPI_STATE_IDLE; 00255 _wlan_cs = 1; 00256 _mutex.unlock(); 00257 } 00258 } 00259 } 00260 00261 } // namespace mbed_cc3000
Generated on Thu Jul 14 2022 05:00:35 by
1.7.2
