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, 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 19:27:43 by
1.7.2
