CC3000 driver updates from David Sidrane

This commit is contained in:
Gregory Nutt 2013-10-23 09:07:32 -06:00
parent 212b5f504c
commit 4cf9540563
6 changed files with 683 additions and 440 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@
* CC30000 from Texas Instruments http://processors.wiki.ti.com/index.php/CC3000 * CC30000 from Texas Instruments http://processors.wiki.ti.com/index.php/CC3000
* *
* See also: * See also:
* http://processors.wiki.ti.com/index.php/CC3000_Host_Driver_Porting_Guide * http://processors.wiki.ti.com/index.php/CC3000_Host_Driver_Porting_Guide
* http://processors.wiki.ti.com/index.php/CC3000_Host_Programming_Guide * http://processors.wiki.ti.com/index.php/CC3000_Host_Programming_Guide
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -61,19 +61,15 @@
* Pre-Processor Definitions * Pre-Processor Definitions
****************************************************************************/ ****************************************************************************/
/* CC3000 Interfaces *********************************************************************/ /* CC3000 Interfaces ********************************************************/
/* Driver support **************************************************************************/ /* Driver support ***********************************************************/
/* This format is used to construct the /dev/input[n] device driver path. It /* This format is used to construct the /dev/input[n] device driver path. It
* defined here so that it will be used consistently in all places. * defined here so that it will be used consistently in all places.
*/ */
/********************************************************************************************
* Public Types
********************************************************************************************/
#define READ 3 #define READ 3
#define READ_COMMAND {READ, 0 , 0 , 0 , 0} #define READ_COMMAND {READ, 0 , 0 , 0 , 0}
#define READ_OFFSET_TO_LENGTH 3 //cmd dmy dmy lh ll #define READ_OFFSET_TO_LENGTH 3 //cmd dmy dmy lh ll
#define WRITE 1 #define WRITE 1
@ -82,38 +78,44 @@
#define SPI_HEADER_SIZE (5) #define SPI_HEADER_SIZE (5)
/****************************************************************************
* Public Types
****************************************************************************/
/* This structure describes the state of one CC3000 driver instance */ /* This structure describes the state of one CC3000 driver instance */
typedef enum {
eSPI_STATE_POWERUP = 0,
eSPI_STATE_INITIALIZED,
eSPI_STATE_IDLE,
eSPI_STATE_WRITE_WAIT_IRQ,
eSPI_STATE_WRITE_PROCEED,
eSPI_STATE_WRITE_DONE,
eSPI_STATE_READ_IRQ,
eSPI_STATE_READ_PROCEED,
eSPI_STATE_READ_READY,
typedef enum
{
eSPI_STATE_POWERUP = 0,
eSPI_STATE_INITIALIZED,
eSPI_STATE_IDLE,
eSPI_STATE_WRITE_WAIT_IRQ,
eSPI_STATE_WRITE_PROCEED,
eSPI_STATE_WRITE_DONE,
eSPI_STATE_READ_IRQ,
eSPI_STATE_READ_PROCEED,
eSPI_STATE_READ_READY,
} eDeviceStates; } eDeviceStates;
struct cc3000_dev_s struct cc3000_dev_s
{ {
#ifdef CONFIG_CC3000_MULTIPLE #ifdef CONFIG_CC3000_MULTIPLE
FAR struct cc3000_dev_s *flink; /* Supports a singly linked list of drivers */ FAR struct cc3000_dev_s *flink; /* Supports a singly linked list of drivers */
#endif #endif
pthread_t workertid; /* Handle for the worker thread */
uint8_t crefs; /* Number of times the device has been opened */ uint8_t crefs; /* Number of times the device has been opened */
uint8_t nwaiters; /* Number of threads waiting for CC3000 data */ uint8_t nwaiters; /* Number of threads waiting for CC3000 data */
uint8_t minor; /* minor */ uint8_t minor; /* minor */
sem_t devsem; /* Manages exclusive access to this structure */ sem_t devsem; /* Manages exclusive access to this structure */
sem_t wrkwaitsem; /* Suspend and resume the delivery of messages */
sem_t waitsem; /* Used to wait for the availability of data */ sem_t waitsem; /* Used to wait for the availability of data */
sem_t readysem; /* Used to wait for Ready Condition from the cc3000 */ sem_t irqsem; /* Used to signal irq from cc3000 */
sem_t readysem; /* Used to wait for Ready Condition from the cc3000 */
FAR struct cc3000_config_s *config; /* Board configuration data */ FAR struct cc3000_config_s *config; /* Board configuration data */
FAR struct spi_dev_s *spi; /* Saved SPI driver instance */ FAR struct spi_dev_s *spi; /* Saved SPI driver instance */
struct work_s work; /* Supports the interrupt handling "bottom half" */ mqd_t queue; /* For unsolicited data delivery */
mqd_t queue; /* For unsolicited data delivery */ eDeviceStates state; /* The device state */
eDeviceStates state; /* The device state */
uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE]; uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE];
ssize_t rx_buffer_len; ssize_t rx_buffer_len;

View File

@ -36,8 +36,11 @@
* Included Files * Included Files
******************************************************************************/ ******************************************************************************/
#include <nuttx/config.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
#include <debug.h>
#include <nuttx/wireless/cc3000/cc3000_common.h> #include <nuttx/wireless/cc3000/cc3000_common.h>
#include <nuttx/wireless/cc3000/hci.h> #include <nuttx/wireless/cc3000/hci.h>
@ -234,8 +237,7 @@ uint8_t *hci_event_handler(void *pRetParams, uint8_t *from, uint8_t *fromlen)
while (1) while (1)
{ {
if (tSLInformation.usEventOrDataReceived != 0) if (tSLInformation.usEventOrDataReceived != 0) {
{
pucReceivedData = (tSLInformation.pucReceivedData); pucReceivedData = (tSLInformation.pucReceivedData);
if (*pucReceivedData == HCI_TYPE_EVNT) if (*pucReceivedData == HCI_TYPE_EVNT)
@ -363,10 +365,11 @@ uint8_t *hci_event_handler(void *pRetParams, uint8_t *from, uint8_t *fromlen)
if (((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == if (((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes ==
ERROR_SOCKET_INACTIVE) ERROR_SOCKET_INACTIVE)
{ {
set_socket_active_status set_socket_active_status
(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); (((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,
} SOCKET_STATUS_INACTIVE);
}
} }
break; break;
@ -435,7 +438,7 @@ uint8_t *hci_event_handler(void *pRetParams, uint8_t *from, uint8_t *fromlen)
pRetParams = ((char *)pRetParams) + 2; pRetParams = ((char *)pRetParams) + 2;
memcpy((uint8_t *)pRetParams, memcpy((uint8_t *)pRetParams,
(char *)(pucReceivedParams + (char *)(pucReceivedParams +
GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2),
GET_SCAN_RESULTS_SSID_MAC_LENGTH); GET_SCAN_RESULTS_SSID_MAC_LENGTH);
break; break;
@ -902,7 +905,36 @@ void SimpleLinkWaitEvent(uint16_t usOpcode, void *pRetParams)
*/ */
tSLInformation.usRxEventOpcode = usOpcode; tSLInformation.usRxEventOpcode = usOpcode;
hci_event_handler(pRetParams, 0, 0); nllvdbg("Looking for usOpcode 0x%x\n",usOpcode);
uint16_t event_type;
do
{
tSLInformation.pucReceivedData = SpiWait();
tSLInformation.usEventOrDataReceived = 1;
STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type);
if (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT)
{
nllvdbg("Evtn:0x%x\n",event_type);
}
if (event_type != usOpcode)
{
if (hci_unsolicited_event_handler() == 1)
{
nllvdbg("Processed Event 0x%x want 0x%x\n",event_type, usOpcode);
}
}
else
{
nllvdbg("Processing usOpcode 0x%x\n",usOpcode);
hci_event_handler(pRetParams, 0, 0);
}
}
while(tSLInformation.usRxEventOpcode != 0);
nllvdbg("Done for usOpcode 0x%x\n",usOpcode);
} }
/***************************************************************************** /*****************************************************************************
@ -928,6 +960,37 @@ void SimpleLinkWaitData(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen)
* after the end of current transaction, i.e. only after data will be received * after the end of current transaction, i.e. only after data will be received
*/ */
tSLInformation.usRxDataPending = 1; nllvdbg("Looking for Data\n");
hci_event_handler(pBuf, from, fromlen); uint16_t event_type;
uint16_t usOpcode = tSLInformation.usRxEventOpcode;
do
{
tSLInformation.pucReceivedData = SpiWait();
tSLInformation.usEventOrDataReceived = 1;
if (*tSLInformation.pucReceivedData == HCI_TYPE_DATA)
{
tSLInformation.usRxDataPending = 1;
hci_event_handler(pBuf, from, fromlen);
break;
}
else
{
STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type);
nllvdbg("Evtn:0x%x\n",event_type);
if (hci_unsolicited_event_handler() == 1)
{
nllvdbg("Processed Event 0x%x want Data! Opcode 0x%x\n",event_type, usOpcode);
}
else
{
nllvdbg("!!!!!usOpcode 0x%x\n",usOpcode);
}
}
}
while(*tSLInformation.pucReceivedData == HCI_TYPE_EVNT);
nllvdbg("Done for Data 0x%x\n",usOpcode);
} }

View File

@ -38,6 +38,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <debug.h>
#include <stdlib.h> #include <stdlib.h>
#include <nuttx/wireless/cc3000/hci.h> #include <nuttx/wireless/cc3000/hci.h>
#include <nuttx/wireless/cc3000/include/sys/socket.h> #include <nuttx/wireless/cc3000/include/sys/socket.h>
@ -139,7 +141,14 @@ int HostFlowControlConsumeBuff(int sd)
{ {
return -1; return -1;
} }
} while (0 == tSLInformation.usNumberOfFreeBuffers);
/* We must yield here for the the Event to get processed that returns
* the buffers
*/
usleep(100000);
}
while (0 == tSLInformation.usNumberOfFreeBuffers);
tSLInformation.usNumberOfFreeBuffers--; tSLInformation.usNumberOfFreeBuffers--;
@ -1213,8 +1222,9 @@ int sendto(long sd, const void *buf, long len, long flags, const sockaddr *to,
int mdnsAdvertiser(uint16_t mdnsEnabled, char * deviceServiceName, int mdnsAdvertiser(uint16_t mdnsEnabled, char * deviceServiceName,
uint16_t deviceServiceNameLength) uint16_t deviceServiceNameLength)
{ {
uint8_t *pTxBuffer;
uint8_t *pArgs;
int ret; int ret;
uint8_t *pTxBuffer, *pArgs;
if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
{ {

View File

@ -59,6 +59,10 @@
# define spivdbg(x...) # define spivdbg(x...)
#endif #endif
/*****************************************************************************
* Private Types
*****************************************************************************/
static struct static struct
{ {
int cc3000fd; int cc3000fd;
@ -66,6 +70,7 @@ static struct
pthread_t unsoliced_thread; pthread_t unsoliced_thread;
bool run; bool run;
uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE]; uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE];
mqd_t queue;
} spiconf; } spiconf;
@ -139,6 +144,27 @@ long SpiRead(uint8_t *pUserBuffer, uint16_t usLength)
return read(spiconf.cc3000fd,pUserBuffer,usLength); return read(spiconf.cc3000fd,pUserBuffer,usLength);
} }
/*****************************************************************************
* Name: SpiRead
*
* Description:
*
* Input Parameters:
* None
*
* Returned Value:
*
*****************************************************************************/
uint8_t *SpiWait(void)
{
int nbytes;
DEBUGASSERT(spiconf.cc3000fd);
nbytes = mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0);
return spiconf.rx_buffer;
}
/***************************************************************************** /*****************************************************************************
* Name: unsoliced_thread_func * Name: unsoliced_thread_func
* *
@ -162,19 +188,20 @@ static void *unsoliced_thread_func(void *parameter)
ioctl(spiconf.cc3000fd, CC3000IOC_GETQUEID, (unsigned long)&minor); ioctl(spiconf.cc3000fd, CC3000IOC_GETQUEID, (unsigned long)&minor);
snprintf(queuename, QUEUE_NAMELEN, QUEUE_FORMAT, minor); snprintf(queuename, QUEUE_NAMELEN, QUEUE_FORMAT, minor);
mqd_t queue = mq_open(queuename,O_RDONLY); spiconf.queue = mq_open(queuename,O_RDONLY);
while(spiconf.run) while(spiconf.run)
{ {
memset(spiconf.rx_buffer,0,sizeof(spiconf.rx_buffer)); memset(spiconf.rx_buffer,0,sizeof(spiconf.rx_buffer));
nbytes = mq_receive(queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0); nbytes = mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0);
if (nbytes > 0) if (nbytes > 0)
{ {
spivdbg("%d Processed\n",nbytes);
spiconf.pfRxHandler(spiconf.rx_buffer); spiconf.pfRxHandler(spiconf.rx_buffer);
} }
} }
mq_close(queue); mq_close(spiconf.queue);
pthread_exit((pthread_addr_t)status); pthread_exit((pthread_addr_t)status);
return (pthread_addr_t)status; return (pthread_addr_t)status;
} }
@ -205,7 +232,12 @@ void SpiOpen(gcSpiHandleRx pfRxHandler)
spiconf.cc3000fd = fd; spiconf.cc3000fd = fd;
spiconf.run = true; spiconf.run = true;
status = pthread_create(&spiconf.unsoliced_thread,NULL, pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
param.sched_priority = SCHED_PRIORITY_DEFAULT-10;
pthread_attr_setschedparam(&attr, &param);
status = pthread_create(&spiconf.unsoliced_thread, &attr,
unsoliced_thread_func, NULL); unsoliced_thread_func, NULL);
DEBUGASSERT(status == 0) DEBUGASSERT(status == 0)
} }
@ -227,15 +259,15 @@ void SpiOpen(gcSpiHandleRx pfRxHandler)
void SpiClose(void) void SpiClose(void)
{ {
if (spiconf.cc3000fd) if (spiconf.cc3000fd)
{ {
int status; int status;
spiconf.run = false; spiconf.run = false;
pthread_cancel(spiconf.unsoliced_thread); pthread_cancel(spiconf.unsoliced_thread);
pthread_join(spiconf.unsoliced_thread, (pthread_addr_t*)&status); pthread_join(spiconf.unsoliced_thread, (pthread_addr_t*)&status);
close(spiconf.cc3000fd); close(spiconf.cc3000fd);
spiconf.cc3000fd = 0; spiconf.cc3000fd = 0;
} }
} }

View File

@ -44,6 +44,7 @@ typedef void (*gcSpiHandleRx)(void *p);
void SpiOpen(gcSpiHandleRx pfRxHandler); void SpiOpen(gcSpiHandleRx pfRxHandler);
void SpiClose(void); void SpiClose(void);
long SpiWrite(uint8_t *pUserBuffer, uint16_t usLength); long SpiWrite(uint8_t *pUserBuffer, uint16_t usLength);
uint8_t *SpiWait(void);
long SpiRead(uint8_t *pUserBuffer, uint16_t usLength); long SpiRead(uint8_t *pUserBuffer, uint16_t usLength);
void SpiResumeSpi(void); void SpiResumeSpi(void);
int CC3000InterruptHandler(int irq, void *context); int CC3000InterruptHandler(int irq, void *context);