Created
April 6, 2014 03:14
-
-
Save AndySze/10001039 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ChibiOS/RT - Copyright (C) 2013 Alan Barr | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
/* This program aims to test a CC3000 using a STM32L152 running ChibiOS. | |
* ChibiOS is on branch stable_2.6.x. This board is not supported in the | |
* mainline, but is available on a fork, here: | |
* https://github.com/alanbarr/ChibiOS-RT/tree/32L152CDISCOVERY | |
* | |
* Instead of using TI's host driver, this program has hard coded in the SPI | |
* commands that emulate what the host driver does in a call to wlan_start(0). | |
* | |
* SPI commands for wlan_start(0): | |
* 1. HCI_CMND_SIMPLE_START | |
* STM32->CC3000: 01 00 05 00 00 01 00 40 01 00 | |
* | |
* 2. COMPLETE | |
* CC3000->STM32: 02 00 00 00 05 04 00 40 01 00 | |
* STM32->CC3000: 03 00 00 | |
* | |
* 3. HCI_CMND_READ_BUFFER_SIZE | |
* STM32->CC3000: 01 00 05 00 00 01 0B 40 00 00 | |
* | |
* 4. HCI_CMND_READ_BUFFER_SIZE Reply | |
* CC3000->Host: 02 00 00 00 09 04 0B 40 04 00 06 DC 05 00 | |
* STM32->CC3000: 03 00 00 | |
* | |
* Pins: | |
* CC3000 | |
* WLAN EN: PB.10 | |
* IRQ: PB.11 | |
* CS: PB.12 | |
* CLK: PB.13 | |
* MISO: PB.14 | |
* MOSI: PB.15 | |
* UART | |
* TX: PA.9 | |
* RX: PA.10 | |
* | |
* Drivers: | |
* SPI: SPID2 (2 MHz, CPOL = Low, CPHA = 2nd Edge) | |
* UART: SD1 (38400 baud, 8-N-1) | |
* | |
*/ | |
#include "ch.h" | |
#include "hal.h" | |
#include "board.h" | |
#include "chstreams.h" | |
#include "chprintf.h" | |
#include "string.h" | |
/* Interrupt pin */ | |
#define CC3000_CH_SPI_IRQ_PORT GPIOB | |
#define CC3000_CH_SPI_IRQ_PAD 11 | |
/*WLAN Pin / VBAT_SW_EN */ | |
#define CC3000_CH_SPI_WLAN_EN_PORT GPIOB | |
#define CC3000_CH_SPI_WLAN_EN_PAD 10 | |
/* SPI_DRIVER */ | |
#define CC3000_CH_SPI_DRIVER SPID2 | |
#define CC3000_CH_SPI_PORT GPIOB | |
#define CC3000_CH_SPI_NSS_PAD 12 | |
#define CC3000_CH_SPI_SCK_PAD 13 | |
#define CC3000_CH_SPI_MISO_PAD 14 | |
#define CC3000_CH_SPI_MOSI_PAD 15 | |
/* Helper for UART */ | |
#define PRINT(STR) chprintf((BaseSequentialStream*)&SD1,"(%s:%d) " STR "\n\r", \ | |
__FILE__, __LINE__, NULL); | |
SPIConfig chSpiConfig; | |
uint8_t simpleStartComamndStream[] = | |
{0x01, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x40, 0x01, 0x00}; | |
uint8_t replyToSimpleStartCommandStream[] = | |
{0x02, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x40, 0x01, 0x00}; | |
uint8_t readBufferSizeCommandStream[] = | |
{0x01, 0x00, 0x05, 0x00, 0x00, 0x01, 0x0B, 0x40, 0x00, 0x00}; | |
uint8_t replyToReadBufferSizeCommandStream[] = | |
{0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x0B, 0x40, 0x04, 0x00, | |
0x06, 0xDC, 0x05, 0x00}; | |
uint8_t readCommand[] = | |
{0x03, 0x00, 0x00}; | |
/* Asserts the CS line */ | |
static void selectCC3000(void) | |
{ | |
chThdSleep(MS2ST(10)); | |
spiSelect(&CC3000_CH_SPI_DRIVER); | |
chThdSleep(MS2ST(10)); | |
} | |
/* De asserts the CS line */ | |
static void unselectCC3000(void) | |
{ | |
chThdSleep(MS2ST(10)); | |
spiUnselect(&CC3000_CH_SPI_DRIVER); | |
chThdSleep(MS2ST(10)); | |
} | |
/* Configures all the pins required for communication with the CC3000. | |
* Takes care to leave the WLAN EN pin low, then introduce a delay before | |
* returning. */ | |
static void setupCC3000Spi(void) | |
{ | |
/* SPI Config */ | |
chSpiConfig.end_cb = NULL; | |
chSpiConfig.ssport = CC3000_CH_SPI_PORT; | |
chSpiConfig.sspad = CC3000_CH_SPI_NSS_PAD; | |
chSpiConfig.cr1 = SPI_CR1_CPHA | /* The second clock transition is capture edge*/ | |
(SPI_CR1_BR_1 | SPI_CR1_BR_0); /* BR: 011 is fp_clk /16 = 32 MHz / 16 = 2 MHz */ | |
/* Setup SPI pins */ | |
palSetPad(CC3000_CH_SPI_PORT, CC3000_CH_SPI_NSS_PAD); | |
palSetPadMode(CC3000_CH_SPI_PORT, CC3000_CH_SPI_NSS_PAD, | |
PAL_MODE_OUTPUT_PUSHPULL | | |
PAL_STM32_OSPEED_LOWEST); /* 400 kHz */ | |
palSetPadMode(CC3000_CH_SPI_PORT, CC3000_CH_SPI_SCK_PAD, | |
PAL_MODE_ALTERNATE(5) | /* SPI */ | |
PAL_STM32_OTYPE_PUSHPULL | | |
PAL_STM32_OSPEED_MID2); /* 10 MHz */ | |
palSetPadMode(CC3000_CH_SPI_PORT, CC3000_CH_SPI_MISO_PAD, | |
PAL_MODE_ALTERNATE(5)); /* SPI */ | |
palSetPadMode(CC3000_CH_SPI_PORT, CC3000_CH_SPI_MOSI_PAD, | |
PAL_MODE_ALTERNATE(5) | /* SPI */ | |
PAL_STM32_OTYPE_PUSHPULL | | |
PAL_STM32_OSPEED_MID2); /* 10 MHz */ | |
/* Setup WLAN EN pin.*/ | |
palClearPad(CC3000_CH_SPI_WLAN_EN_PORT, CC3000_CH_SPI_WLAN_EN_PAD); | |
palSetPadMode(CC3000_CH_SPI_WLAN_EN_PORT, CC3000_CH_SPI_WLAN_EN_PAD, | |
PAL_MODE_OUTPUT_PUSHPULL | | |
PAL_STM32_OSPEED_LOWEST); /* 400 kHz */ | |
/* Setup IRQ pin */ | |
palSetPadMode(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD, PAL_MODE_INPUT); | |
spiObjectInit(&CC3000_CH_SPI_DRIVER); | |
spiStart(&CC3000_CH_SPI_DRIVER, &chSpiConfig); | |
chThdSleep(MS2ST(200)); | |
} | |
/* Sets EN high and waits for CC3000 to ready IRQ line */ | |
static void turnOnCC3000(void) | |
{ | |
/* EN high */ | |
palSetPad(CC3000_CH_SPI_WLAN_EN_PORT, CC3000_CH_SPI_WLAN_EN_PAD); | |
/* IRQ should go high then low */ | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 1); | |
chThdSleep(MS2ST(100)); | |
} | |
/* Writes HCI_CMND_SIMPLE_START and checks reply. */ | |
static void simpleStart(void) | |
{ | |
uint8_t rxBuffer[20]; | |
uint8_t ctr; | |
memset(rxBuffer, 0, sizeof(rxBuffer)); | |
/* Write */ | |
selectCC3000(); | |
chThdSleep(US2ST(50)); | |
spiSend(&CC3000_CH_SPI_DRIVER, 4, simpleStartComamndStream); | |
chThdSleep(US2ST(50)); | |
spiSend(&CC3000_CH_SPI_DRIVER, sizeof(simpleStartComamndStream) - 4, | |
simpleStartComamndStream + 4); | |
unselectCC3000(); | |
/* IRQ should go high */ | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
/* IRQ should go low */ | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 1); | |
/* Read 10 bytes. */ | |
selectCC3000(); | |
spiExchange(&CC3000_CH_SPI_DRIVER, | |
sizeof(readCommand), | |
readCommand, | |
rxBuffer); | |
spiReceive(&CC3000_CH_SPI_DRIVER, | |
10 - sizeof(readCommand), | |
&rxBuffer[sizeof(readCommand)]); | |
unselectCC3000(); | |
/* IRQ should go high */ | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
PRINT("Read the following:"); | |
for(ctr=0; ctr<10; ctr++) | |
{ | |
chprintf((BaseSequentialStream*)&SD1, "0x%x ", rxBuffer[ctr]); | |
} | |
chprintf((BaseSequentialStream*)&SD1, "\n\r", rxBuffer[ctr]); | |
/* Error Check function - No point continuing if the received 10 bytes | |
* are not as expected. */ | |
if (memcmp(rxBuffer, replyToSimpleStartCommandStream, 10) != 0) | |
{ | |
PRINT("ERROR: Bytes not as expected.\n\r"); | |
while(1); | |
} | |
} | |
static void getBufferSize(void) | |
{ | |
uint8_t rxBuffer[20]; | |
uint8_t ctr; | |
memset(rxBuffer, 0, sizeof(rxBuffer)); | |
/* IRQ is still high ? */ | |
while(palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
/* Write */ | |
selectCC3000(); | |
/* Wait for IRQ to go low */ | |
while(palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 1); | |
spiSend(&CC3000_CH_SPI_DRIVER, 10, readBufferSizeCommandStream); | |
unselectCC3000(); | |
/* Wait for IRQ to go high */ | |
while(palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
/* Wait for IRQ to go low */ | |
while(palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 1); | |
/* Read all 14 bytes */ | |
selectCC3000(); | |
spiExchange(&CC3000_CH_SPI_DRIVER, | |
sizeof(readCommand), | |
readCommand, | |
rxBuffer); | |
spiReceive(&CC3000_CH_SPI_DRIVER, | |
14 - sizeof(readCommand), | |
&rxBuffer[sizeof(readCommand)]); | |
unselectCC3000(); | |
/* IRQ should go high */ | |
while (palReadPad(CC3000_CH_SPI_IRQ_PORT, CC3000_CH_SPI_IRQ_PAD) == 0); | |
PRINT("Read the following:"); | |
for(ctr=0; ctr<14; ctr++) | |
{ | |
chprintf((BaseSequentialStream*)&SD1, "0x%x ", rxBuffer[ctr]); | |
} | |
chprintf((BaseSequentialStream*)&SD1, "\n\r", rxBuffer[ctr]); | |
/* Error Check function - No point continuing if the received 14 bytes | |
* are not as expected. */ | |
if (memcmp(rxBuffer, replyToReadBufferSizeCommandStream, 14) != 0) | |
{ | |
PRINT("ERROR: Bytes not as expected.:\n\r"); | |
while(1); | |
} | |
} | |
/* Attempts to emulate wlan_start(0), checking responses along the way. */ | |
static void testCC3000Spi(void) | |
{ | |
PRINT("About to start test..."); | |
setupCC3000Spi(); | |
turnOnCC3000(); | |
simpleStart(); | |
getBufferSize(); | |
PRINT("Test completed OK."); | |
/* LED ON */ | |
palSetPad(GPIOB, GPIOB_LED4); | |
/* Turn off CC3000 */ | |
palClearPad(CC3000_CH_SPI_WLAN_EN_PORT, CC3000_CH_SPI_WLAN_EN_PAD); | |
while(1); | |
} | |
int main(void) | |
{ | |
halInit(); | |
chSysInit(); | |
/* Led for debugging */ | |
palClearPad(GPIOB, GPIOB_LED4); | |
palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_OUTPUT_PUSHPULL); | |
/* UART */ | |
sdStart(&SD1, NULL); | |
palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); | |
palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); | |
/* Start Test - Never returns regardless of pass or fail */ | |
testCC3000Spi(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment