cc3000 driver with expanded buffers.

Fork of cc3000_hostdriver_mbedsocket by Martin Kojtal

Committer:
heroic
Date:
Tue May 06 22:38:34 2014 +0000
Revision:
56:9ab991c1d2db
Parent:
53:66e86aa98dbe
Child:
57:8caf996d7b6a
Stop hci event handler from locking up in the situation where the micro thinks there's an event about to happen and the cc3000 disagrees.

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;
Kojto 45:50ab13d8f2dc 109 // check the total length of the packet in order to figure out if padding is necessary
Kojto 45:50ab13d8f2dc 110 if(!(length & 0x0001)) {
Kojto 20:30b6ed7bf8fd 111 pad++;
Kojto 45:50ab13d8f2dc 112 }
Kojto 45:50ab13d8f2dc 113 buffer[0] = WRITE;
Kojto 45:50ab13d8f2dc 114 buffer[1] = HI(length + pad);
Kojto 45:50ab13d8f2dc 115 buffer[2] = LO(length + pad);
Kojto 45:50ab13d8f2dc 116 buffer[3] = 0;
Kojto 45:50ab13d8f2dc 117 buffer[4] = 0;
Kojto 20:30b6ed7bf8fd 118
Kojto 45:50ab13d8f2dc 119 length += (SPI_HEADER_SIZE + pad);
Kojto 20:30b6ed7bf8fd 120
Kojto 45:50ab13d8f2dc 121 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
Kojto 45:50ab13d8f2dc 122 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
Kojto 45:50ab13d8f2dc 123 uint8_t *transmit_buffer = _simple_link.get_transmit_buffer();
Kojto 45:50ab13d8f2dc 124 if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
heroic 56:9ab991c1d2db 125 NVIC_SystemReset();
Kojto 45:50ab13d8f2dc 126 }
Kojto 45:50ab13d8f2dc 127
Kojto 45:50ab13d8f2dc 128 if (_spi_info.spi_state == eSPI_STATE_POWERUP) {
Kojto 45:50ab13d8f2dc 129 while (_spi_info.spi_state != eSPI_STATE_INITIALIZED);
Kojto 45:50ab13d8f2dc 130 }
Kojto 20:30b6ed7bf8fd 131
Kojto 45:50ab13d8f2dc 132 if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) {
Kojto 45:50ab13d8f2dc 133 // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command
Kojto 45:50ab13d8f2dc 134 first_write(buffer, length);
Kojto 45:50ab13d8f2dc 135 } else {
Kojto 45:50ab13d8f2dc 136 // Prevent occurence of a race condition when 2 back to back packets are sent to the
Kojto 45:50ab13d8f2dc 137 // device, so the state will move to IDLE and once again to not IDLE due to IRQ
Kojto 45:50ab13d8f2dc 138 wlan_irq_disable();
Kojto 20:30b6ed7bf8fd 139
Kojto 45:50ab13d8f2dc 140 while (_spi_info.spi_state != eSPI_STATE_IDLE);
Kojto 20:30b6ed7bf8fd 141
Kojto 45:50ab13d8f2dc 142 _spi_info.spi_state = eSPI_STATE_WRITE_IRQ;
Kojto 45:50ab13d8f2dc 143 //_spi_info.pTxPacket = buffer;
Kojto 45:50ab13d8f2dc 144 _spi_info.tx_packet_length = length;
Kojto 20:30b6ed7bf8fd 145
Kojto 45:50ab13d8f2dc 146 // Assert the CS line and wait until the IRQ line is active, then initialize the write operation
Kojto 45:50ab13d8f2dc 147 _wlan_cs = 0;
Kojto 20:30b6ed7bf8fd 148
Kojto 45:50ab13d8f2dc 149 wlan_irq_enable();
Kojto 45:50ab13d8f2dc 150 }
Kojto 20:30b6ed7bf8fd 151
Kojto 45:50ab13d8f2dc 152 // Wait until the transaction ends
Kojto 45:50ab13d8f2dc 153 while (_spi_info.spi_state != eSPI_STATE_IDLE);
Kojto 20:30b6ed7bf8fd 154
Kojto 45:50ab13d8f2dc 155 return 0;
Kojto 20:30b6ed7bf8fd 156 }
Kojto 20:30b6ed7bf8fd 157
Kojto 20:30b6ed7bf8fd 158 void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) {
Kojto 45:50ab13d8f2dc 159 while(size) {
Kojto 20:30b6ed7bf8fd 160 _wlan_spi.write(*data++);
Kojto 20:30b6ed7bf8fd 161 size--;
Kojto 45:50ab13d8f2dc 162 }
Kojto 20:30b6ed7bf8fd 163 }
Kojto 20:30b6ed7bf8fd 164
Kojto 20:30b6ed7bf8fd 165 void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) {
Kojto 45:50ab13d8f2dc 166 for (uint32_t i = 0; i < size; i++) {
Kojto 45:50ab13d8f2dc 167 data[i] = _wlan_spi.write(0x03);
Kojto 45:50ab13d8f2dc 168 }
Kojto 20:30b6ed7bf8fd 169 }
Kojto 20:30b6ed7bf8fd 170
Kojto 20:30b6ed7bf8fd 171 uint32_t cc3000_spi::read_data_cont() {
Kojto 45:50ab13d8f2dc 172 int32_t data_to_recv;
Kojto 45:50ab13d8f2dc 173 uint8_t *evnt_buff, type;
Kojto 20:30b6ed7bf8fd 174
Kojto 20:30b6ed7bf8fd 175 //determine the packet type
Kojto 20:30b6ed7bf8fd 176 evnt_buff = _simple_link.get_received_buffer();
Kojto 20:30b6ed7bf8fd 177 data_to_recv = 0;
Kojto 20:30b6ed7bf8fd 178 STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
Kojto 20:30b6ed7bf8fd 179
Kojto 45:50ab13d8f2dc 180 switch(type) {
Kojto 20:30b6ed7bf8fd 181 case HCI_TYPE_DATA:
Kojto 45:50ab13d8f2dc 182 // Read the remaining data..
Kojto 45:50ab13d8f2dc 183 STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv);
Kojto 45:50ab13d8f2dc 184 if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) {
Kojto 45:50ab13d8f2dc 185 data_to_recv++;
Kojto 45:50ab13d8f2dc 186 }
Kojto 20:30b6ed7bf8fd 187
Kojto 45:50ab13d8f2dc 188 if (data_to_recv) {
Kojto 20:30b6ed7bf8fd 189 read_synchronous(evnt_buff + 10, data_to_recv);
Kojto 45:50ab13d8f2dc 190 }
Kojto 20:30b6ed7bf8fd 191 break;
Kojto 20:30b6ed7bf8fd 192 case HCI_TYPE_EVNT:
Kojto 45:50ab13d8f2dc 193 // Calculate the rest length of the data
Kojto 20:30b6ed7bf8fd 194 STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv);
Kojto 45:50ab13d8f2dc 195 data_to_recv -= 1;
Kojto 45:50ab13d8f2dc 196 // Add padding byte if needed
Kojto 45:50ab13d8f2dc 197 if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) {
Kojto 45:50ab13d8f2dc 198 data_to_recv++;
Kojto 45:50ab13d8f2dc 199 }
Kojto 20:30b6ed7bf8fd 200
Kojto 45:50ab13d8f2dc 201 if (data_to_recv) {
Kojto 20:30b6ed7bf8fd 202 read_synchronous(evnt_buff + 10, data_to_recv);
Kojto 45:50ab13d8f2dc 203 }
Kojto 20:30b6ed7bf8fd 204
Kojto 45:50ab13d8f2dc 205 _spi_info.spi_state = eSPI_STATE_READ_EOT;
Kojto 20:30b6ed7bf8fd 206 break;
Kojto 20:30b6ed7bf8fd 207 }
Kojto 45:50ab13d8f2dc 208 return 0;
Kojto 20:30b6ed7bf8fd 209 }
Kojto 20:30b6ed7bf8fd 210
heroic 53:66e86aa98dbe 211 void cc3000_spi::set_wlan_en(uint8_t value) {
Kojto 20:30b6ed7bf8fd 212 if (value) {
Kojto 20:30b6ed7bf8fd 213 _wlan_en = 1;
Kojto 20:30b6ed7bf8fd 214 } else {
Kojto 20:30b6ed7bf8fd 215 _wlan_en = 0;
Kojto 20:30b6ed7bf8fd 216 }
Kojto 20:30b6ed7bf8fd 217 }
Kojto 20:30b6ed7bf8fd 218
Kojto 20:30b6ed7bf8fd 219 void cc3000_spi::WLAN_IRQHandler() {
Kojto 45:50ab13d8f2dc 220 if (_process_irq) {
Kojto 45:50ab13d8f2dc 221 if (_spi_info.spi_state == eSPI_STATE_POWERUP) {
Kojto 45:50ab13d8f2dc 222 // Inform HCI Layer that IRQ occured after powerup
Kojto 45:50ab13d8f2dc 223 _spi_info.spi_state = eSPI_STATE_INITIALIZED;
Kojto 45:50ab13d8f2dc 224 } else if (_spi_info.spi_state == eSPI_STATE_IDLE) {
Kojto 45:50ab13d8f2dc 225 _spi_info.spi_state = eSPI_STATE_READ_IRQ;
Kojto 45:50ab13d8f2dc 226 /* IRQ line goes low - acknowledge it */
Kojto 45:50ab13d8f2dc 227 _wlan_cs = 0;
Kojto 45:50ab13d8f2dc 228 read_synchronous(_simple_link.get_received_buffer(), 10);
Kojto 45:50ab13d8f2dc 229 _spi_info.spi_state = eSPI_STATE_READ_EOT;
Kojto 20:30b6ed7bf8fd 230
Kojto 45:50ab13d8f2dc 231 // The header was read - continue with the payload read
Kojto 45:50ab13d8f2dc 232 if (!read_data_cont()) {
Kojto 45:50ab13d8f2dc 233 // All the data was read - finalize handling by switching to the task
Kojto 45:50ab13d8f2dc 234 // Trigger Rx processing
Kojto 45:50ab13d8f2dc 235 wlan_irq_disable();
Kojto 45:50ab13d8f2dc 236 _wlan_cs = 1;
Kojto 45:50ab13d8f2dc 237 // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
Kojto 45:50ab13d8f2dc 238 // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
Kojto 45:50ab13d8f2dc 239 uint8_t *received_buffer = _simple_link.get_received_buffer();
Kojto 45:50ab13d8f2dc 240 if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
heroic 52:ad6514e66b3b 241 // we're probably going to die anyway, if a real buffer overrun has happened.
heroic 52:ad6514e66b3b 242 // try to fix it up and go anyway. - jls
heroic 56:9ab991c1d2db 243 NVIC_SystemReset();
Kojto 45:50ab13d8f2dc 244 }
Kojto 45:50ab13d8f2dc 245
Kojto 45:50ab13d8f2dc 246 _spi_info.spi_state = eSPI_STATE_IDLE;
Kojto 45:50ab13d8f2dc 247 _event.received_handler(received_buffer + SPI_HEADER_SIZE);
Kojto 45:50ab13d8f2dc 248 }
Kojto 45:50ab13d8f2dc 249 } else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) {
Kojto 45:50ab13d8f2dc 250 write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length);
Kojto 45:50ab13d8f2dc 251 _spi_info.spi_state = eSPI_STATE_IDLE;
Kojto 45:50ab13d8f2dc 252 _wlan_cs = 1;
Kojto 45:50ab13d8f2dc 253 }
Kojto 45:50ab13d8f2dc 254 }
Kojto 20:30b6ed7bf8fd 255 }
Kojto 20:30b6ed7bf8fd 256
Kojto 45:50ab13d8f2dc 257 } // namespace mbed_cc3000