Added mutex for multiple SPI devices on the same SPI bus

Fork of cc3000_hostdriver_mbedsocket by Martin Kojtal

Committer:
Kojto
Date:
Thu Sep 19 07:55:14 2013 +0000
Revision:
0:615c697c33b0
Child:
20:30b6ed7bf8fd
initial commit

Who changed what in which revision?

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