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, uint32_t max_tx, uint32_t max_rx) 00047 : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _event(event), _simple_link(simple_link), _max_tx(max_tx), _max_rx(max_rx) { 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[_max_tx - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00125 DBG_CC("System halted - TX buffer overflow detected (buffer size: %d).", _max_tx); 00126 while (1); 00127 } 00128 00129 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00130 while (_spi_info.spi_state != eSPI_STATE_INITIALIZED); 00131 } 00132 00133 if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) { 00134 // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command 00135 first_write(buffer, length); 00136 } else { 00137 // Prevent occurence of a race condition when 2 back to back packets are sent to the 00138 // device, so the state will move to IDLE and once again to not IDLE due to IRQ 00139 wlan_irq_disable(); 00140 00141 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00142 00143 _spi_info.spi_state = eSPI_STATE_WRITE_IRQ; 00144 //_spi_info.pTxPacket = buffer; 00145 _spi_info.tx_packet_length = length; 00146 00147 // Assert the CS line and wait until the IRQ line is active, then initialize the write operation 00148 _wlan_cs = 0; 00149 00150 wlan_irq_enable(); 00151 } 00152 00153 // Wait until the transaction ends 00154 while (_spi_info.spi_state != eSPI_STATE_IDLE); 00155 00156 return 0; 00157 } 00158 00159 void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) { 00160 while(size) { 00161 _wlan_spi.write(*data++); 00162 size--; 00163 } 00164 } 00165 00166 void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) { 00167 for (uint32_t i = 0; i < size; i++) { 00168 data[i] = _wlan_spi.write(0x03); 00169 } 00170 } 00171 00172 uint32_t cc3000_spi::read_data_cont() { 00173 int32_t data_to_recv; 00174 uint8_t *evnt_buff, type; 00175 00176 //determine the packet type 00177 evnt_buff = _simple_link.get_received_buffer(); 00178 data_to_recv = 0; 00179 STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); 00180 00181 switch(type) { 00182 case HCI_TYPE_DATA: 00183 // Read the remaining data.. 00184 STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); 00185 if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { 00186 data_to_recv++; 00187 } 00188 00189 if (data_to_recv) { 00190 read_synchronous(evnt_buff + 10, data_to_recv); 00191 } 00192 break; 00193 case HCI_TYPE_EVNT: 00194 // Calculate the rest length of the data 00195 STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); 00196 data_to_recv -= 1; 00197 // Add padding byte if needed 00198 if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { 00199 data_to_recv++; 00200 } 00201 00202 if (data_to_recv) { 00203 read_synchronous(evnt_buff + 10, data_to_recv); 00204 } 00205 00206 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00207 break; 00208 } 00209 return 0; 00210 } 00211 00212 void cc3000_spi::set_wlan_en(uint8_t value) { 00213 if (value) { 00214 _wlan_en = 1; 00215 } else { 00216 _wlan_en = 0; 00217 } 00218 } 00219 00220 void cc3000_spi::WLAN_IRQHandler() { 00221 if (_process_irq) { 00222 if (_spi_info.spi_state == eSPI_STATE_POWERUP) { 00223 // Inform HCI Layer that IRQ occured after powerup 00224 _spi_info.spi_state = eSPI_STATE_INITIALIZED; 00225 } else if (_spi_info.spi_state == eSPI_STATE_IDLE) { 00226 _spi_info.spi_state = eSPI_STATE_READ_IRQ; 00227 /* IRQ line goes low - acknowledge it */ 00228 _wlan_cs = 0; 00229 read_synchronous(_simple_link.get_received_buffer(), 10); 00230 _spi_info.spi_state = eSPI_STATE_READ_EOT; 00231 00232 // The header was read - continue with the payload read 00233 if (!read_data_cont()) { 00234 // All the data was read - finalize handling by switching to the task 00235 // Trigger Rx processing 00236 wlan_irq_disable(); 00237 _wlan_cs = 1; 00238 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) 00239 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! 00240 uint8_t *received_buffer = _simple_link.get_received_buffer(); 00241 if (received_buffer[_max_rx - 1] != CC3000_BUFFER_MAGIC_NUMBER) { 00242 DBG_CC("System halted - RX buffer overflow detected (buffer size: %d).", _max_rx); 00243 while (1); 00244 } 00245 00246 _spi_info.spi_state = eSPI_STATE_IDLE; 00247 _event.received_handler(received_buffer + SPI_HEADER_SIZE); 00248 } 00249 } else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) { 00250 write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length); 00251 _spi_info.spi_state = eSPI_STATE_IDLE; 00252 _wlan_cs = 1; 00253 } 00254 } 00255 } 00256 00257 } // namespace mbed_cc3000
Generated on Fri Jul 15 2022 02:23:47 by
1.7.2
