Skip to content

Commit

Permalink
Merge pull request #30 from spark/m-mcgowan/spibus_arbiter
Browse files Browse the repository at this point in the history
Use Mat McGowan's SPI bus arbitration code
  • Loading branch information
Zachary Crockett committed Jul 17, 2014
2 parents 8c045db + 6509c83 commit 160e2df
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 41 deletions.
28 changes: 12 additions & 16 deletions CC3000_Host_Driver/evnt_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "hw_config.h"
#include "debug.h"
#include "spark_macros.h"
#include <stdatomic.h>

//*****************************************************************************
// COMMON DEFINES
Expand Down Expand Up @@ -120,7 +121,7 @@
// GLOBAL VARAIABLES
//*****************************************************************************

UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL;
static volatile UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL;
uint32_t cc3000__event_timeout_ms = 0;

//*****************************************************************************
Expand Down Expand Up @@ -834,20 +835,20 @@ INT32 hci_unsolicited_event_handler(void)
//*****************************************************************************
void set_socket_active_status(INT32 Sd, INT32 Status)
{
DEBUG("Sd=%d, Status %s",Sd, Status == SOCKET_STATUS_ACTIVE ? "SOCKET_STATUS_ACTIVE" : "SOCKET_STATUS_IACTIVE");
DEBUG("Sd=%d, Status %s",Sd, Status == SOCKET_STATUS_ACTIVE ? "SOCKET_STATUS_ACTIVE" : "SOCKET_STATUS_INACTIVE");
if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status))
{
uint32_t is = __get_PRIMASK();
__disable_irq();
socket_active_status &= ~(1 << Sd); /* clean socket's mask */
socket_active_status |= (Status << Sd); /* set new socket's mask */
if ((is & 1) == 0) {
__enable_irq();
for (;;) {
INT32 oldStatus = socket_active_status;
INT32 newStatus = oldStatus;
newStatus &= ~(1 << Sd); /* clean socket's mask */
newStatus |= (Status << Sd); /* set new socket's mask */
if (__sync_bool_compare_and_swap(&socket_active_status, oldStatus, newStatus))
break;
}
}
}


//*****************************************************************************
//
//! hci_event_unsol_flowcontrol_handler
Expand Down Expand Up @@ -881,8 +882,8 @@ INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent)
pReadPayload += FLOW_CONTROL_EVENT_SIZE;
}

tSLInformation.usNumberOfFreeBuffers += temp;
tSLInformation.NumberOfReleasedPackets += temp;
__sync_add_and_fetch(&tSLInformation.usNumberOfFreeBuffers, temp);
__sync_add_and_fetch(&tSLInformation.NumberOfReleasedPackets, temp);

return(ESUCCESS);
}
Expand All @@ -903,12 +904,7 @@ INT32 get_socket_active_status(INT32 Sd)
long rv = SOCKET_STATUS_INACTIVE;
if(M_IS_VALID_SD(Sd))
{
uint32_t is = __get_PRIMASK();
__disable_irq();
rv = (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE;
if ((is & 1) == 0) {
__enable_irq();
}
}
return rv;
}
Expand Down
2 changes: 0 additions & 2 deletions CC3000_Host_Driver/evnt_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ extern INT32 hci_unsolicited_event_handler(void);
#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7))
#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE))

extern UINT32 socket_active_status;

extern void set_socket_active_status(INT32 Sd, INT32 Status);
extern INT32 get_socket_active_status(INT32 Sd);

Expand Down
13 changes: 8 additions & 5 deletions CC3000_Host_Driver/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ INT16 HostFlowControlConsumeBuff(INT16 sd)
/* wait in busy loop */
volatile system_tick_t start = GetSystem1MsTick();

bool stop = false;
do
{
// In case last transmission failed then we will return the last failure
Expand All @@ -145,10 +146,12 @@ INT16 HostFlowControlConsumeBuff(INT16 sd)
return -1;
}

} while(0 == tSLInformation.usNumberOfFreeBuffers);

tSLInformation.usNumberOfFreeBuffers--;

// Do an atomic decrement if > 0
UINT16 freeBuffers = tSLInformation.usNumberOfFreeBuffers;
if (0 < freeBuffers) {
stop = __sync_bool_compare_and_swap(&tSLInformation.usNumberOfFreeBuffers, freeBuffers, freeBuffers-1);
}
} while (!stop);
return 0;
#else

Expand Down Expand Up @@ -1149,7 +1152,7 @@ INT16 sendto(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *
//
//*****************************************************************************

INT16 mdnsAdvertiser(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
INT16 mdnsAdvertiser(UINT16 mdnsEnabled, const CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
{
INT8 ret;
UINT8 *pTxBuffer, *pArgs;
Expand Down
2 changes: 1 addition & 1 deletion CC3000_Host_Driver/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ extern INT16 sendto(INT32 sd, const void *buf, INT32 len, INT32 flags,
//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
//
//*****************************************************************************
extern INT16 mdnsAdvertiser(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength);
extern INT16 mdnsAdvertiser(UINT16 mdnsEnabled, const CHAR * deviceServiceName, UINT16 deviceServiceNameLength);


//*****************************************************************************
Expand Down
4 changes: 2 additions & 2 deletions CC3000_Host_Driver/wlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ void wlan_stop(void)
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
UINT8 *bssid, UINT8 *key, INT32 key_len)
INT32 wlan_connect(UINT32 ulSecType, const CHAR *ssid, INT32 ssid_len,
const UINT8 *bssid, const UINT8 *key, INT32 key_len)
{
INT32 ret;
UINT8 *ptr;
Expand Down
4 changes: 2 additions & 2 deletions CC3000_Host_Driver/wlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ extern void wlan_stop(void);
//
//*****************************************************************************
#ifndef CC3000_TINY_DRIVER
extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
UINT8 *bssid, UINT8 *key, INT32 key_len);
extern INT32 wlan_connect(UINT32 ulSecType, const CHAR *ssid, INT32 ssid_len,
const UINT8 *bssid, const UINT8 *key, INT32 key_len);
#else
extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len);

Expand Down
2 changes: 2 additions & 0 deletions SPARK_Firmware_Driver/inc/cc3000_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,6 @@ extern void SpiResumeSpi(void);
extern void SPI_DMA_IntHandler(void);
extern void SPI_EXTI_IntHandler(void);

extern void handle_spi_request();

#endif /* __CC3000_SPI_H */
7 changes: 7 additions & 0 deletions SPARK_Firmware_Driver/inc/hw_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
#include "cc3000_common.h"
#include "usb_type.h"

enum SpiBusOwner {
BUS_OWNER_NONE = 0,
BUS_OWNER_CC3000 = 1,
BUS_OWNER_SFLASH = 2
};


/* Exported types ------------------------------------------------------------*/
typedef enum
{
Expand Down
30 changes: 30 additions & 0 deletions SPARK_Firmware_Driver/inc/spi_bus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* File: spi_bus.h
* Author: mat
*
* Created on 30 June 2014, 14:25
*/

#ifndef SPI_BUS_H
#define SPI_BUS_H

#ifdef __cplusplus
extern "C" {
#endif

void reset_bus();

int try_acquire_spi_bus(int owner);

void acquire_spi_bus(int owner);

void release_spi_bus(int owner);

int current_bus_owner();

#ifdef __cplusplus
}
#endif

#endif /* SPI_BUS_H */

1 change: 1 addition & 0 deletions SPARK_Firmware_Driver/src/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ CSRC += $(TARGET_SPARK_SRC_PATH)/system_stm32f10x.c
CSRC += $(TARGET_SPARK_SRC_PATH)/usb_pwr.c
CSRC += $(TARGET_SPARK_SRC_PATH)/debug.c
CSRC += $(TARGET_SPARK_SRC_PATH)/panic.c
CSRC += $(TARGET_SPARK_SRC_PATH)/spi_bus.c

# C++ source files included in this build.
CPPSRC +=
Expand Down
42 changes: 31 additions & 11 deletions SPARK_Firmware_Driver/src/cc3000_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "socket.h"
#include "spark_macros.h"
#include "debug.h"
#include "spi_bus.h"

#define READ_COMMAND {READ, 0 , 0 , 0 , 0}
#define READ_OFFSET_TO_LENGTH 3 //cmd dmy dmy lh ll
Expand All @@ -52,6 +53,7 @@ typedef enum
eSPI_STATE_READ_IRQ,
eSPI_STATE_READ_PROCEED,
eSPI_STATE_READ_READY,
eSPI_STATE_READ_PREP_IRQ
} eCC3000States;


Expand Down Expand Up @@ -117,13 +119,17 @@ static inline eCC3000States State()

static inline eCC3000States SetState(eCC3000States ns, eCSActions cs)
{

intState save = DISABLE_INT();
eCC3000States os = sSpiInformation.ulSpiState;
sSpiInformation.ulSpiState = ns;
if (cs != eNone)
switch (cs)
{
cs == eAssert ? ASSERT_CS() : DEASSERT_CS();
case eAssert:
ASSERT_CS();
break;
case eDeAssert:
DEASSERT_CS();
break;
}
ENABLE_INT(save);
return os;
Expand Down Expand Up @@ -325,6 +331,7 @@ long SpiWrite(unsigned char *ucBuf, unsigned short usLength)
if(NotAborted)
{
NotAborted = Reserve(eSPI_STATE_WRITE_WAIT_IRQ);
WARN("CC3000 SpiWrite acquire bus");
if(NotAborted)
{
usLength = SpiSetUp(ucBuf, usLength);
Expand Down Expand Up @@ -396,9 +403,9 @@ void SPI_DMA_IntHandler(void)
/* Clear SPI_DMA Interrupt Pending Flags */
DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG);

sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
SpiPauseSpi();
DEASSERT_CS();
SetState(eSPI_STATE_IDLE, eDeAssert);
WARN("CC3000 DmaHandler release read spi bus");
// Call out to the Unsolicited handler
// It will handle the event or leave it there for an outstanding opcode
// It it handles it the it Will resume the SPI ISR
Expand Down Expand Up @@ -426,9 +433,8 @@ void SPI_DMA_IntHandler(void)
}
else
{
DEASSERT_CS();

sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
SetState(eSPI_STATE_IDLE, eDeAssert);
WARN("CC3000 DmaHandler release write spi bus");
}
}
break;
Expand All @@ -440,6 +446,16 @@ void SPI_DMA_IntHandler(void)
}
}

void handle_spi_request()
{
if (State() == eSPI_STATE_READ_PREP_IRQ && try_acquire_spi_bus(BUS_OWNER_CC3000))
{
DEBUG("Handling CC3000 request on main thread");
SetState(eSPI_STATE_READ_IRQ, eAssert);
SpiIO(eRead, sSpiInformation.pRxPacket, arraySize(spi_readCommand), FALSE);
DEBUG("...done");
}
}

/**
* @brief The handler for Interrupt that is generated when CC3000 brings the
Expand All @@ -458,9 +474,13 @@ void SPI_EXTI_IntHandler(void)
sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED;
break;
case eSPI_STATE_IDLE:
sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ;
ASSERT_CS();
SpiIO(eRead, sSpiInformation.pRxPacket, arraySize(spi_readCommand), FALSE);
if (try_acquire_spi_bus(BUS_OWNER_CC3000)) {
SetState(eSPI_STATE_READ_IRQ, eAssert);
SpiIO(eRead, sSpiInformation.pRxPacket, arraySize(spi_readCommand), FALSE);
} else {
SetState(eSPI_STATE_READ_PREP_IRQ, eNone);
WARN("CC3000 cannot lock bus - scheduling later (owner=%d)", current_bus_owner());
}
break;
case eSPI_STATE_WRITE_WAIT_IRQ:
sSpiInformation.ulSpiState = eSPI_STATE_WRITE_PROCEED;
Expand Down
10 changes: 8 additions & 2 deletions SPARK_Firmware_Driver/src/hw_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "usb_lib.h"
#include "usb_pwr.h"
#include <string.h>
#include "spi_bus.h"
#include "debug.h"
#include "cc3000_spi.h"

/* Private typedef -----------------------------------------------------------*/

Expand Down Expand Up @@ -952,8 +955,8 @@ void CC3000_SPI_DMA_Channels(FunctionalState NewState)
/* Select CC3000: ChipSelect pin low */
void CC3000_CS_LOW(void)
{
acquire_spi_bus(BUS_OWNER_CC3000);
CC3000_SPI->CR1 &= ((uint16_t)0xFFBF);
sFLASH_CS_HIGH();
CC3000_SPI->CR1 = CC3000_SPI_CR | ((uint16_t)0x0040);
GPIO_ResetBits(CC3000_WIFI_CS_GPIO_PORT, CC3000_WIFI_CS_GPIO_PIN);
}
Expand All @@ -962,6 +965,7 @@ void CC3000_CS_LOW(void)
void CC3000_CS_HIGH(void)
{
GPIO_SetBits(CC3000_WIFI_CS_GPIO_PORT, CC3000_WIFI_CS_GPIO_PIN);
release_spi_bus(BUS_OWNER_CC3000);
}

/* CC3000 Hardware related callbacks passed to wlan_init */
Expand Down Expand Up @@ -1133,8 +1137,8 @@ void sFLASH_SPI_Init(void)
/* Select sFLASH: Chip Select pin low */
void sFLASH_CS_LOW(void)
{
acquire_spi_bus(BUS_OWNER_SFLASH);
sFLASH_SPI->CR1 &= ((uint16_t)0xFFBF);
CC3000_CS_HIGH();
sFLASH_SPI->CR1 = sFLASH_SPI_CR | ((uint16_t)0x0040);
GPIO_ResetBits(sFLASH_MEM_CS_GPIO_PORT, sFLASH_MEM_CS_GPIO_PIN);
}
Expand All @@ -1143,6 +1147,8 @@ void sFLASH_CS_LOW(void)
void sFLASH_CS_HIGH(void)
{
GPIO_SetBits(sFLASH_MEM_CS_GPIO_PORT, sFLASH_MEM_CS_GPIO_PIN);
release_spi_bus(BUS_OWNER_SFLASH);
handle_spi_request();
}

/*******************************************************************************
Expand Down
45 changes: 45 additions & 0 deletions SPARK_Firmware_Driver/src/spi_bus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <stdint.h>
#include <stdatomic.h>
#include "spi_bus.h"
#include "debug.h"
#include "hw_config.h"

#ifndef SPI_BUS_ARBITER
#define SPI_BUS_ARBITER 1
#endif

volatile int spi_bus_lock = 0;

void reset_bus() { spi_bus_lock = 0; }

int try_acquire_spi_bus(int owner) {
#if SPI_BUS_ARBITER
__sync_synchronize();
return spi_bus_lock==owner || __sync_bool_compare_and_swap(&spi_bus_lock, 0, owner);
#else
return 1;
#endif
}

void acquire_spi_bus(int owner) {
#if SPI_BUS_ARBITER
while (!try_acquire_spi_bus(owner));
#endif
}

int try_release_spi_bus(int owner) {
#if SPI_BUS_ARBITER
__sync_synchronize();
return spi_bus_lock==0 || __sync_bool_compare_and_swap(&spi_bus_lock, owner, 0);
#else
return 1;
#endif
}

void release_spi_bus(int owner) {
#if SPI_BUS_ARBITER
while (!try_release_spi_bus(owner));
#endif
}

int current_bus_owner() { return spi_bus_lock; }

0 comments on commit 160e2df

Please sign in to comment.