cc3000 driver with expanded buffers.

Fork of cc3000_hostdriver_mbedsocket by Martin Kojtal

Committer:
heroic
Date:
Wed May 07 02:53:08 2014 +0000
Revision:
57:8caf996d7b6a
Parent:
56:9ab991c1d2db
Yet more debugging.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kojto 20:30b6ed7bf8fd 1 /*****************************************************************************
Kojto 20:30b6ed7bf8fd 2 *
Kojto 20:30b6ed7bf8fd 3 * C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to
Kojto 20:30b6ed7bf8fd 4 * Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and
Kojto 20:30b6ed7bf8fd 5 * provided help.
Kojto 20:30b6ed7bf8fd 6 *
Kojto 20:30b6ed7bf8fd 7 * This version of "host driver" uses CC3000 Host Driver Implementation. Thus
Kojto 20:30b6ed7bf8fd 8 * read the following copyright:
Kojto 20:30b6ed7bf8fd 9 *
Kojto 20:30b6ed7bf8fd 10 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
Kojto 20:30b6ed7bf8fd 11 *
Kojto 20:30b6ed7bf8fd 12 * Redistribution and use in source and binary forms, with or without
Kojto 20:30b6ed7bf8fd 13 * modification, are permitted provided that the following conditions
Kojto 20:30b6ed7bf8fd 14 * are met:
Kojto 20:30b6ed7bf8fd 15 *
Kojto 20:30b6ed7bf8fd 16 * Redistributions of source code must retain the above copyright
Kojto 20:30b6ed7bf8fd 17 * notice, this list of conditions and the following disclaimer.
Kojto 20:30b6ed7bf8fd 18 *
Kojto 20:30b6ed7bf8fd 19 * Redistributions in binary form must reproduce the above copyright
Kojto 20:30b6ed7bf8fd 20 * notice, this list of conditions and the following disclaimer in the
Kojto 20:30b6ed7bf8fd 21 * documentation and/or other materials provided with the
Kojto 20:30b6ed7bf8fd 22 * distribution.
Kojto 20:30b6ed7bf8fd 23 *
Kojto 20:30b6ed7bf8fd 24 * Neither the name of Texas Instruments Incorporated nor the names of
Kojto 20:30b6ed7bf8fd 25 * its contributors may be used to endorse or promote products derived
Kojto 20:30b6ed7bf8fd 26 * from this software without specific prior written permission.
Kojto 20:30b6ed7bf8fd 27 *
Kojto 20:30b6ed7bf8fd 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Kojto 20:30b6ed7bf8fd 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Kojto 20:30b6ed7bf8fd 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Kojto 20:30b6ed7bf8fd 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Kojto 20:30b6ed7bf8fd 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Kojto 20:30b6ed7bf8fd 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Kojto 20:30b6ed7bf8fd 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Kojto 20:30b6ed7bf8fd 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Kojto 20:30b6ed7bf8fd 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Kojto 20:30b6ed7bf8fd 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Kojto 20:30b6ed7bf8fd 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Kojto 20:30b6ed7bf8fd 39 *
Kojto 20:30b6ed7bf8fd 40 *****************************************************************************/
Kojto 20:30b6ed7bf8fd 41 #include "cc3000.h"
Kojto 20:30b6ed7bf8fd 42 #include "cc3000_spi.h"
Kojto 20:30b6ed7bf8fd 43
Kojto 20:30b6ed7bf8fd 44 namespace mbed_cc3000 {
Kojto 20:30b6ed7bf8fd 45
Kojto 45:50ab13d8f2dc 46 cc3000_spi::cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, cc3000_event &event, cc3000_simple_link &simple_link)
Kojto 45:50ab13d8f2dc 47 : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _event(event), _simple_link(simple_link) {
Kojto 20:30b6ed7bf8fd 48
Kojto 20:30b6ed7bf8fd 49 _wlan_spi.format(8,1);
heroic 50:039f2518e98a 50 _wlan_spi.frequency(12000000);
Kojto 45:50ab13d8f2dc 51 _wlan_irq.fall(this, &cc3000_spi::WLAN_IRQHandler);
Kojto 20:30b6ed7bf8fd 52
Kojto 20:30b6ed7bf8fd 53 _wlan_en = 0;
Kojto 20:30b6ed7bf8fd 54 _wlan_cs = 1;
Kojto 45:50ab13d8f2dc 55 wait_ms(50); /* mbed board delay */
Kojto 20:30b6ed7bf8fd 56 }
Kojto 20:30b6ed7bf8fd 57
Kojto 20:30b6ed7bf8fd 58 cc3000_spi::~cc3000_spi() {
Kojto 20:30b6ed7bf8fd 59
Kojto 20:30b6ed7bf8fd 60 }
Kojto 20:30b6ed7bf8fd 61
Kojto 20:30b6ed7bf8fd 62 void cc3000_spi::wlan_irq_enable()
Kojto 20:30b6ed7bf8fd 63 {
Kojto 45:50ab13d8f2dc 64 _process_irq = true;
Kojto 45:50ab13d8f2dc 65 //_wlan_irq.enable_irq();
Kojto 44:960b73df5981 66
Kojto 45:50ab13d8f2dc 67 if (wlan_irq_read() == 0) {
Kojto 44:960b73df5981 68 WLAN_IRQHandler();
Kojto 44:960b73df5981 69 }
Kojto 20:30b6ed7bf8fd 70 }
Kojto 20:30b6ed7bf8fd 71
Kojto 20:30b6ed7bf8fd 72 void cc3000_spi::wlan_irq_disable() {
Kojto 45:50ab13d8f2dc 73 _process_irq = false;
Kojto 45:50ab13d8f2dc 74 //_wlan_irq.disable_irq();
Kojto 20:30b6ed7bf8fd 75 }
Kojto 20:30b6ed7bf8fd 76
Kojto 20:30b6ed7bf8fd 77 uint32_t cc3000_spi::wlan_irq_read() {
Kojto 20:30b6ed7bf8fd 78 return _wlan_irq.read();
Kojto 20:30b6ed7bf8fd 79 }
Kojto 20:30b6ed7bf8fd 80
Kojto 20:30b6ed7bf8fd 81 void cc3000_spi::close() {
Kojto 20:30b6ed7bf8fd 82 wlan_irq_disable();
Kojto 20:30b6ed7bf8fd 83 }
Kojto 20:30b6ed7bf8fd 84
Kojto 20:30b6ed7bf8fd 85 void cc3000_spi::open() {
Kojto 20:30b6ed7bf8fd 86 _spi_info.spi_state = eSPI_STATE_POWERUP;
Kojto 20:30b6ed7bf8fd 87 _spi_info.tx_packet_length = 0;
Kojto 20:30b6ed7bf8fd 88 _spi_info.rx_packet_length = 0;
Kojto 20:30b6ed7bf8fd 89 wlan_irq_enable();
Kojto 20:30b6ed7bf8fd 90 }
Kojto 20:30b6ed7bf8fd 91
Kojto 20:30b6ed7bf8fd 92 uint32_t cc3000_spi::first_write(uint8_t *buffer, uint16_t length) {
Kojto 20:30b6ed7bf8fd 93 _wlan_cs = 0;
Kojto 20:30b6ed7bf8fd 94 wait_us(50);
Kojto 20:30b6ed7bf8fd 95
Kojto 20:30b6ed7bf8fd 96 /* first 4 bytes of the data */
Kojto 20:30b6ed7bf8fd 97 write_synchronous(buffer, 4);
Kojto 20:30b6ed7bf8fd 98 wait_us(50);
Kojto 20:30b6ed7bf8fd 99 write_synchronous(buffer + 4, length - 4);
Kojto 20:30b6ed7bf8fd 100 _spi_info.spi_state = eSPI_STATE_IDLE;
Kojto 20:30b6ed7bf8fd 101 _wlan_cs = 1;
Kojto 20:30b6ed7bf8fd 102
Kojto 20:30b6ed7bf8fd 103 return 0;
Kojto 20:30b6ed7bf8fd 104 }
Kojto 20:30b6ed7bf8fd 105
Kojto 20:30b6ed7bf8fd 106
Kojto 20:30b6ed7bf8fd 107 uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) {
Kojto 20:30b6ed7bf8fd 108 uint8_t pad = 0;
heroic 57:8caf996d7b6a 109 uint32_t escapeCounter;
Kojto 45:50ab13d8f2dc 110 // check the total length of the packet in order to figure out if padding is necessary
Kojto 45:50ab13d8f2dc 111 if(!(length & 0x0001)) {
Kojto 20:30b6ed7bf8fd 112 pad++;
Kojto 45:50ab13d8f2dc 113 }
Kojto 45:50ab13d8f2dc 114 buffer[0] = WRITE;
Kojto 45:50ab13d8f2dc 115 buffer[1] = HI(length + pad);
Kojto 45:50ab13d8f2dc 116 buffer[2] = LO(length + pad);
Kojto 45:50ab13d8f2dc 117 buffer[3] = 0;
Kojto 45:50ab13d8f2dc 118 buffer[4] = 0;
Kojto 20:30b6ed7bf8fd 119
Kojto 45:50ab13d8f2dc 120 length += (SPI_HEADER_SIZE + pad);
Kojto 20:30b6ed7bf8fd 121
Kojto 45:50ab13d8f2dc 122 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
Kojto 45:50ab13d8f2dc 123 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
Kojto 45:50ab13d8f2dc 124 uint8_t *transmit_buffer = _simple_link.get_transmit_buffer();
Kojto 45:50ab13d8f2dc 125 if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
heroic 56:9ab991c1d2db 126 NVIC_SystemReset();
Kojto 45:50ab13d8f2dc 127 }
Kojto 45:50ab13d8f2dc 128
Kojto 45:50ab13d8f2dc 129 if (_spi_info.spi_state == eSPI_STATE_POWERUP) {
heroic 57:8caf996d7b6a 130 escapeCounter = 100000000;
heroic 57:8caf996d7b6a 131 while (_spi_info.spi_state != eSPI_STATE_INITIALIZED) {
heroic 57:8caf996d7b6a 132 escapeCounter--;
heroic 57:8caf996d7b6a 133 if (!escapeCounter)
heroic 57:8caf996d7b6a 134 break;
heroic 57:8caf996d7b6a 135 }
Kojto 45:50ab13d8f2dc 136 }
Kojto 20:30b6ed7bf8fd 137
Kojto 45:50ab13d8f2dc 138 if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) {
Kojto 45:50ab13d8f2dc 139 // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command
Kojto 45:50ab13d8f2dc 140 first_write(buffer, length);
Kojto 45:50ab13d8f2dc 141 } else {
Kojto 45:50ab13d8f2dc 142 // Prevent occurence of a race condition when 2 back to back packets are sent to the
Kojto 45:50ab13d8f2dc 143 // device, so the state will move to IDLE and once again to not IDLE due to IRQ
Kojto 45:50ab13d8f2dc 144 wlan_irq_disable();
Kojto 20:30b6ed7bf8fd 145
heroic 57:8caf996d7b6a 146 escapeCounter = 100000000;
heroic 57:8caf996d7b6a 147 while (_spi_info.spi_state != eSPI_STATE_IDLE){
heroic 57:8caf996d7b6a 148 escapeCounter--;
heroic 57:8caf996d7b6a 149 if (!escapeCounter)
heroic 57:8caf996d7b6a 150 break;
heroic 57:8caf996d7b6a 151 }
Kojto 20:30b6ed7bf8fd 152
Kojto 45:50ab13d8f2dc 153 _spi_info.spi_state = eSPI_STATE_WRITE_IRQ;
Kojto 45:50ab13d8f2dc 154 //_spi_info.pTxPacket = buffer;
Kojto 45:50ab13d8f2dc 155 _spi_info.tx_packet_length = length;
Kojto 20:30b6ed7bf8fd 156
Kojto 45:50ab13d8f2dc 157 // Assert the CS line and wait until the IRQ line is active, then initialize the write operation
Kojto 45:50ab13d8f2dc 158 _wlan_cs = 0;
Kojto 20:30b6ed7bf8fd 159
Kojto 45:50ab13d8f2dc 160 wlan_irq_enable();
Kojto 45:50ab13d8f2dc 161 }
Kojto 20:30b6ed7bf8fd 162
Kojto 45:50ab13d8f2dc 163 // Wait until the transaction ends
heroic 57:8caf996d7b6a 164 escapeCounter = 100000000;
heroic 57:8caf996d7b6a 165 while (_spi_info.spi_state != eSPI_STATE_IDLE) {
heroic 57:8caf996d7b6a 166 escapeCounter--;
heroic 57:8caf996d7b6a 167 if (!escapeCounter)
heroic 57:8caf996d7b6a 168 break;
heroic 57:8caf996d7b6a 169 }
Kojto 45:50ab13d8f2dc 170 return 0;
Kojto 20:30b6ed7bf8fd 171 }
Kojto 20:30b6ed7bf8fd 172
Kojto 20:30b6ed7bf8fd 173 void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) {
Kojto 45:50ab13d8f2dc 174 while(size) {
Kojto 20:30b6ed7bf8fd 175 _wlan_spi.write(*data++);
Kojto 20:30b6ed7bf8fd 176 size--;
Kojto 45:50ab13d8f2dc 177 }
Kojto 20:30b6ed7bf8fd 178 }
Kojto 20:30b6ed7bf8fd 179
Kojto 20:30b6ed7bf8fd 180 void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) {
Kojto 45:50ab13d8f2dc 181 for (uint32_t i = 0; i < size; i++) {
Kojto 45:50ab13d8f2dc 182 data[i] = _wlan_spi.write(0x03);
Kojto 45:50ab13d8f2dc 183 }
Kojto 20:30b6ed7bf8fd 184 }
Kojto 20:30b6ed7bf8fd 185
Kojto 20:30b6ed7bf8fd 186 uint32_t cc3000_spi::read_data_cont() {
Kojto 45:50ab13d8f2dc 187 int32_t data_to_recv;
Kojto 45:50ab13d8f2dc 188 uint8_t *evnt_buff, type;
Kojto 20:30b6ed7bf8fd 189
Kojto 20:30b6ed7bf8fd 190 //determine the packet type
Kojto 20:30b6ed7bf8fd 191 evnt_buff = _simple_link.get_received_buffer();
Kojto 20:30b6ed7bf8fd 192 data_to_recv = 0;
Kojto 20:30b6ed7bf8fd 193 STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
Kojto 20:30b6ed7bf8fd 194
Kojto 45:50ab13d8f2dc 195 switch(type) {
Kojto 20:30b6ed7bf8fd 196 case HCI_TYPE_DATA:
Kojto 45:50ab13d8f2dc 197 // Read the remaining data..
Kojto 45:50ab13d8f2dc 198 STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv);
Kojto 45:50ab13d8f2dc 199 if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) {
Kojto 45:50ab13d8f2dc 200 data_to_recv++;
Kojto 45:50ab13d8f2dc 201 }
Kojto 20:30b6ed7bf8fd 202
Kojto 45:50ab13d8f2dc 203 if (data_to_recv) {
Kojto 20:30b6ed7bf8fd 204 read_synchronous(evnt_buff + 10, data_to_recv);
Kojto 45:50ab13d8f2dc 205 }
Kojto 20:30b6ed7bf8fd 206 break;
Kojto 20:30b6ed7bf8fd 207 case HCI_TYPE_EVNT:
Kojto 45:50ab13d8f2dc 208 // Calculate the rest length of the data
Kojto 20:30b6ed7bf8fd 209 STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv);
Kojto 45:50ab13d8f2dc 210 data_to_recv -= 1;
Kojto 45:50ab13d8f2dc 211 // Add padding byte if needed
Kojto 45:50ab13d8f2dc 212 if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) {
Kojto 45:50ab13d8f2dc 213 data_to_recv++;
Kojto 45:50ab13d8f2dc 214 }
Kojto 20:30b6ed7bf8fd 215
Kojto 45:50ab13d8f2dc 216 if (data_to_recv) {
Kojto 20:30b6ed7bf8fd 217 read_synchronous(evnt_buff + 10, data_to_recv);
Kojto 45:50ab13d8f2dc 218 }
Kojto 20:30b6ed7bf8fd 219
Kojto 45:50ab13d8f2dc 220 _spi_info.spi_state = eSPI_STATE_READ_EOT;
Kojto 20:30b6ed7bf8fd 221 break;
Kojto 20:30b6ed7bf8fd 222 }
Kojto 45:50ab13d8f2dc 223 return 0;
Kojto 20:30b6ed7bf8fd 224 }
Kojto 20:30b6ed7bf8fd 225
heroic 53:66e86aa98dbe 226 void cc3000_spi::set_wlan_en(uint8_t value) {
Kojto 20:30b6ed7bf8fd 227 if (value) {
Kojto 20:30b6ed7bf8fd 228 _wlan_en = 1;
Kojto 20:30b6ed7bf8fd 229 } else {
Kojto 20:30b6ed7bf8fd 230 _wlan_en = 0;
Kojto 20:30b6ed7bf8fd 231 }
Kojto 20:30b6ed7bf8fd 232 }
Kojto 20:30b6ed7bf8fd 233
Kojto 20:30b6ed7bf8fd 234 void cc3000_spi::WLAN_IRQHandler() {
Kojto 45:50ab13d8f2dc 235 if (_process_irq) {
Kojto 45:50ab13d8f2dc 236 if (_spi_info.spi_state == eSPI_STATE_POWERUP) {
Kojto 45:50ab13d8f2dc 237 // Inform HCI Layer that IRQ occured after powerup
Kojto 45:50ab13d8f2dc 238 _spi_info.spi_state = eSPI_STATE_INITIALIZED;
Kojto 45:50ab13d8f2dc 239 } else if (_spi_info.spi_state == eSPI_STATE_IDLE) {
Kojto 45:50ab13d8f2dc 240 _spi_info.spi_state = eSPI_STATE_READ_IRQ;
Kojto 45:50ab13d8f2dc 241 /* IRQ line goes low - acknowledge it */
Kojto 45:50ab13d8f2dc 242 _wlan_cs = 0;
Kojto 45:50ab13d8f2dc 243 read_synchronous(_simple_link.get_received_buffer(), 10);
Kojto 45:50ab13d8f2dc 244 _spi_info.spi_state = eSPI_STATE_READ_EOT;
Kojto 20:30b6ed7bf8fd 245
Kojto 45:50ab13d8f2dc 246 // The header was read - continue with the payload read
Kojto 45:50ab13d8f2dc 247 if (!read_data_cont()) {
Kojto 45:50ab13d8f2dc 248 // All the data was read - finalize handling by switching to the task
Kojto 45:50ab13d8f2dc 249 // Trigger Rx processing
Kojto 45:50ab13d8f2dc 250 wlan_irq_disable();
Kojto 45:50ab13d8f2dc 251 _wlan_cs = 1;
Kojto 45:50ab13d8f2dc 252 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
Kojto 45:50ab13d8f2dc 253 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
Kojto 45:50ab13d8f2dc 254 uint8_t *received_buffer = _simple_link.get_received_buffer();
Kojto 45:50ab13d8f2dc 255 if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
heroic 52:ad6514e66b3b 256 // we're probably going to die anyway, if a real buffer overrun has happened.
heroic 52:ad6514e66b3b 257 // try to fix it up and go anyway. - jls
heroic 56:9ab991c1d2db 258 NVIC_SystemReset();
Kojto 45:50ab13d8f2dc 259 }
Kojto 45:50ab13d8f2dc 260
Kojto 45:50ab13d8f2dc 261 _spi_info.spi_state = eSPI_STATE_IDLE;
Kojto 45:50ab13d8f2dc 262 _event.received_handler(received_buffer + SPI_HEADER_SIZE);
Kojto 45:50ab13d8f2dc 263 }
Kojto 45:50ab13d8f2dc 264 } else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) {
Kojto 45:50ab13d8f2dc 265 write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length);
Kojto 45:50ab13d8f2dc 266 _spi_info.spi_state = eSPI_STATE_IDLE;
Kojto 45:50ab13d8f2dc 267 _wlan_cs = 1;
Kojto 45:50ab13d8f2dc 268 }
Kojto 45:50ab13d8f2dc 269 }
Kojto 20:30b6ed7bf8fd 270 }
Kojto 20:30b6ed7bf8fd 271
Kojto 45:50ab13d8f2dc 272 } // namespace mbed_cc3000