SWRA704 June   2021 CC3120 , CC3130 , CC3135

 

  1.   Trademarks
  2. 1Introduction
  3. 2Porting the Host Driver
    1. 2.1 Porting Layer Files
    2. 2.2 Driver Enable/Disable
    3. 2.3 SPI Interface
      1. 2.3.1 Hardware Setup and Configuring Clocks
    4. 2.4 Memory Management
    5. 2.5 OS Abstraction: FreeRTOS
    6. 2.6 Timestamp Mechanism
    7. 2.7 Asynchronous Event Handler Routines
  4. 3Tips for Porting
    1. 3.1 Hardware Setup
    2. 3.2 Servicepack
    3. 3.3 Starting the Wi-Fi Driver in the Application Code
    4. 3.4 Configuring Clocks on the STM32L4
    5. 3.5 Terminal I/O Printing
    6. 3.6 Location of the Host Driver and Porting Files
    7. 3.7 Updating to the Latest Host Driver Version
  5. 4References
  6. 5License Information

Hardware Setup and Configuring Clocks

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.