Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
* 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
You can’t perform that action at this time.