SWRA704 June 2021 CC3120 , CC3130 , CC3135
The host communication interface can support SPI or UART. For this application report, the SPI interface is used.
The communication interface requires functionality for open, close, read, write, and registering an interrupt handler routine for the host IRQ signal. It is recommended that the sl_IfOpen open function also initializes the SPI/UART interface. The interface can be initialized outside of this function, but then it is the application's responsibility to ensure this is complete before starting the host driver.
user.h:
#define _SlFd_t Fd_t
#define sl_IfOpen spi_Open
#define sl_IfClose spi_Close
#define sl_IfRead spi_Read
#define sl_IfWrite spi_Write
#define sl_IfRegIntHdlr(InterruptHdl, pValue) NwpRegisterInterruptHandler(InterruptHdl, pValue)
cc_pal.h
defines a suggested pin configuration for the host
interface. To see the mapped pins, see Section 3.1.
cc_pal.h:
/* CC31xx pin configuration */
/* Definition for SPI clock resources */
#define SPIx SPI2
#define SPIx_CLK_ENABLE() __SPI2_CLK_ENABLE()
#define SPIx_SCK_GPIO_CLK_ENABLE() __GPIOB_CLK_ENABLE()
#define SPIx_MISO_GPIO_CLK_ENABLE() __GPIOB_CLK_ENABLE()
#define SPIx_MOSI_GPIO_CLK_ENABLE() __GPIOB_CLK_ENABLE()
#define SPIx_FORCE_RESET() __SPI2_FORCE_RESET()
#define SPIx_RELEASE_RESET() __SPI2_RELEASE_RESET()
/* Definition for SPIx Pins */
#define SPIx_SCK_PIN GPIO_PIN_13
#define SPIx_SCK_GPIO_PORT GPIOB
#define SPIx_SCK_AF GPIO_AF5_SPI2
#define SPIx_MISO_PIN GPIO_PIN_14
#define SPIx_MISO_GPIO_PORT GPIOB
#define SPIx_MISO_AF GPIO_AF5_SPI2
#define SPIx_MOSI_PIN GPIO_PIN_15
#define SPIx_MOSI_GPIO_PORT GPIOB
#define SPIx_MOSI_AF GPIO_AF5_SPI2
/* SPI GPIO CS */
#define SPI_CS_PORT GPIOH
#define SPI_CS_PIN GPIO_PIN_13
/* Definition for SPIx's NVIC */
#define SPIx_IRQn SPI2_IRQn
#define SPIx_IRQHandler SPI2_IRQHandler
/* HOST-IRQ*/
#define HOST_IRQ_PORT GPIOA
#define HOST_IRQ_PIN GPIO_PIN_0
#define HOST_nHIB_PORT GPIOH
#define HOST_nHIB_PIN GPIO_PIN_15
extern Fd_t spi_Open(char *ifName, unsigned long flags);
extern int spi_Close(Fd_t fd);
extern int spi_Read(Fd_t fd, unsigned char *pBuff, int len);
extern int spi_Write(Fd_t fd, unsigned char *pBuff, int len);
extern int NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl, void* pValue);
void EXTI0_IRQHandler(void);
cc_pal.c
implements the
SPI interface. spi_Open (defined as
sl_IfOpen) sets the SPI parameters. This example uses a GPIO
as a software chip select, so the SPI NSS is defined as soft. For more details about
setting up the SPI clock, see Section 3.4.
cc_pal.c:
#define SPI_TIMEOUT_MAX 0x1000
SPI_HandleTypeDef SpiHandle;
static void GPIO_Init(GPIO_TypeDef *GPIO_PORT, unsigned short GPIO_PIN);
static void CC31xx_InterruptEnable(void);
static void CC31xx_InterruptDisable(void);
/****************************************************************************
* spi_Open
****************************************************************************/
Fd_t spi_Open(char *ifName, unsigned long flags)
{
/* Initialize the WiFi driver */
/* Set the SPI parameters */
SpiHandle.Instance = SPIx;
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
SpiHandle.Init.CRCPolynomial = 7;
SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
SpiHandle.Init.NSS = SPI_NSS_SOFT;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
if(HAL_SPI_Init(&SpiHandle) != HAL_OK)
{
/* Initialization Error */
while(1);
}
/* Initialize CS */
GPIO_Init(SPI_CS_PORT, SPI_CS_PIN);
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);
/* Enable IRQ */
CC31xx_InterruptEnable();
/* Initialize nHIB */
GPIO_Init(HOST_nHIB_PORT, HOST_nHIB_PIN);
NwpPowerOff();
/* Wait 50 ms */
HAL_Delay(50);
return 0;
}
/****************************************************************************
* spi_Close
****************************************************************************/
int spi_Close(Fd_t fd)
{
/* Disable Interrupt */
CC31xx_InterruptDisable();
/* Deinitialize SPI */
HAL_SPI_DeInit(&SpiHandle);
return 0;
}
/****************************************************************************
* spi_Read
****************************************************************************/
int spi_Read(Fd_t fd,
unsigned char *pBuff,
int len)
{
/* Assert CS */
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Receive(&SpiHandle, pBuff, len, SPI_TIMEOUT_MAX);
/* Deassert CS */
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);
return len;
}
/****************************************************************************
* spi_Write
****************************************************************************/
int spi_Write(Fd_t fd,
unsigned char *pBuff,
int len)
{
/* Assert CS */
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&SpiHandle, pBuff, len, SPI_TIMEOUT_MAX);
/* Deassert CS */
HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS_PIN, GPIO_PIN_SET);
return len;
}
/****************************************************************************
* NwpRegisterInterruptHandler - set the interrupt handler function from the host driver
****************************************************************************/
int NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl,
void* pValue)
{
pIrqEventHandler = InterruptHdl;
return 0;
}
The following code snippets are helper
functions for spi_Open
that should also go in
cc_pal.c.
GPIO_Init
is used to
initialize the GPIOs in the host interface (nHib and
CS
) and their clocks.
/****************************************************************************
* GPIO_Init: General GPIO initialization. Used by spi_Open
****************************************************************************/
static void GPIO_Init(GPIO_TypeDef *GPIO_PORT, unsigned short GPIO_PIN)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOx clock */
if(GPIO_PORT == GPIOA)
__GPIOA_CLK_ENABLE();
else if(GPIO_PORT == GPIOB)
__GPIOB_CLK_ENABLE();
else if(GPIO_PORT == GPIOC)
__GPIOC_CLK_ENABLE();
else if(GPIO_PORT == GPIOD)
__GPIOD_CLK_ENABLE();
else if(GPIO_PORT == GPIOE)
__GPIOE_CLK_ENABLE();
else if(GPIO_PORT == GPIOF)
__GPIOF_CLK_ENABLE();
else if(GPIO_PORT == GPIOG)
__GPIOG_CLK_ENABLE();
else if(GPIO_PORT == GPIOH)
__GPIOH_CLK_ENABLE();
/* Configure pin as input floating */
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = GPIO_PIN;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
}
CC31xx_InterruptEnable
registers the host IRQ signal as an interrupt wake source. This host IRQ signal is
required to handle asynchronous events from the network processor.
P_EVENT_HANDLER pIrqEventHandler = 0;
uint32_t irqPriority = 5;
/****************************************************************************
* CC31xx_InterruptEnable
****************************************************************************/
void CC31xx_InterruptEnable()
{
/* Configure EXTI Line0 (connected to PA0 pin) in interrupt mode */
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOx clock */
if(HOST_IRQ_PORT == GPIOA)
__GPIOA_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOB)
__GPIOB_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOC)
__GPIOC_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOD)
__GPIOD_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOE)
__GPIOE_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOF)
__GPIOF_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOG)
__GPIOG_CLK_ENABLE();
else if(HOST_IRQ_PORT == GPIOH)
__GPIOH_CLK_ENABLE();
/* Configure PA0 pin as input floating */
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = HOST_IRQ_PIN;
HAL_GPIO_Init(HOST_IRQ_PORT, &GPIO_InitStructure);
/* Enable and set EXTI Line0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_IRQn, irqPriority, 0U);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
CC31xx_InterruptDisable
disables the host IRQ interrupt.
/****************************************************************************
* CC31xx_InterruptDisable
****************************************************************************/
void CC31xx_InterruptDisable()
{
HAL_NVIC_DisableIRQ(EXTI0_IRQn);
}
EXTI0_IRQHandler
is an
interrupt handler for the STM32L4 EXT1 IRQ. If defined, this replaces the standard
function in the HAL layer.
/****************************************************************************
* @brief EXTI line detection callbacks
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
****************************************************************************/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if((GPIO_Pin == HOST_IRQ_PIN) &&
(NULL != pIrqEventHandler) )
{
pIrqEventHandler(0);
}
}
/****************************************************************************
* @brief This function handles External line 0 interrupt request.
* @param None
* @retval None
****************************************************************************/
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(HOST_IRQ_PIN);
}
For this application, the APIs for host
IRQ mask and unmask (sl_IfMaskIntHdlr
and
sl_IfUnMaskIntHdlr
) are not used. These are typically not required
for the SPI interface.