I’m using CC3235 device from Texas Instruments. This is basically a WiFi Network Processor. In one of the example codes I tried replacing treads with tasks. Some of it worked and some of it did not. The same are as follows:
- in main_freertos.c code below, I replace mainThread with mainTask and the code ran without any error. However, in platform.c file, when I tried replacing spawn thread with spawn task, the code did not run at all. It ends up stating that “the processor received a fault interrupt”.
/*
* ======== main_freertos.c ========
*/
#include <stdint.h>
/* POSIX Header files */
#include <pthread.h>
/* RTOS header files */
#include "FreeRTOS.h"
#include "task.h"
/* TI-DRIVERS Header files */
#include "ti_drivers_config.h"
/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
extern void * mainThread(void *arg0);
/* Stack size in bytes */
#define THREADSTACKSIZE 4096
/*
* ======== main ========
*/
int main(void)
{
pthread_t thread;
pthread_attr_t pAttrs;
struct sched_param priParam;
int retc;
int detachState;
/* Call board init functions */
Board_init();
/* Set priority and stack size attributes */
pthread_attr_init(&pAttrs);
priParam.sched_priority = 1;
detachState = PTHREAD_CREATE_DETACHED;
retc = pthread_attr_setdetachstate(&pAttrs, detachState);
if(retc != 0)
{
/* pthread_attr_setdetachstate() failed */
while(1)
{
;
}
}
pthread_attr_setschedparam(&pAttrs, &priParam);
retc |= pthread_attr_setstacksize(&pAttrs, THREADSTACKSIZE);
if(retc != 0)
{
/* pthread_attr_setstacksize() failed */
while(1)
{
;
}
}
retc = pthread_create(&thread, &pAttrs, mainThread, NULL);
if(retc != 0)
{
/* pthread_create() failed */
while(1)
{
;
}
}
/* Start the FreeRTOS scheduler */
vTaskStartScheduler();
return (0);
}
//*****************************************************************************
//
//! \brief Application defined malloc failed hook
//!
//! \param none
//!
//! \return none
//!
//*****************************************************************************
void vApplicationMallocFailedHook()
{
/* Handle Memory Allocation Errors */
while(1)
{
}
}
//*****************************************************************************
//
//! \brief Application defined stack overflow hook
//!
//! \param none
//!
//! \return none
//!
//*****************************************************************************
void vApplicationStackOverflowHook(TaskHandle_t pxTask,
char *pcTaskName)
{
//Handle FreeRTOS Stack Overflow
while(1)
{
}
}
void vApplicationTickHook(void)
{
/*
* This function will be called by each tick interrupt if
* configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
* added here, but the tick hook is called from an interrupt context, so
* code must not attempt to block, and only the interrupt safe FreeRTOS API
* functions can be used (those that end in FromISR()).
*/
}
void vPreSleepProcessing(uint32_t ulExpectedIdleTime)
{
}
//*****************************************************************************
//
//! \brief Application defined idle task hook
//!
//! \param none
//!
//! \return none
//!
//*****************************************************************************
void
vApplicationIdleHook(void)
{
/* Handle Idle Hook for Profiling, Power Management etc */
}
//*****************************************************************************
//
//! \brief Overwrite the GCC _sbrk function which check the heap limit related
//! to the stack pointer.
//! In case of freertos this checking will fail.
//! \param none
//!
//! \return none
//!
//*****************************************************************************
#if defined (__GNUC__)
void * _sbrk(uint32_t delta)
{
extern char _end; /* Defined by the linker */
extern char __HeapLimit;
static char *heap_end;
static char *heap_limit;
char *prev_heap_end;
if(heap_end == 0)
{
heap_end = &_end;
heap_limit = &__HeapLimit;
}
prev_heap_end = heap_end;
if(prev_heap_end + delta > heap_limit)
{
return((void *) -1L);
}
heap_end += delta;
return((void *) prev_heap_end);
}
#endif
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/net/wifi/slnetifwifi.h>
#include <ti/display/Display.h>
#include <ti/drivers/SPI.h>
// TI-Driver includes
#include "ti_drivers_config.h"
#include "pthread.h"
#define APPLICATION_NAME ("UDP Echo")
#define APPLICATION_VERSION ("1.0.0.0")
#define DEVICE_ERROR ("Device error, please refer \"DEVICE ERRORS CODES\" section in errors.h")
#define WLAN_ERROR ("WLAN error, please refer \"WLAN ERRORS CODES\" section in errors.h")
#define SL_STOP_TIMEOUT (200)
#define UDPPORT (1000)
#define SPAWN_TASK_PRIORITY (9)
#define TASK_STACK_SIZE (2048)
#define SLNET_IF_WIFI_PRIO (5)
#define SLNET_IF_WIFI_NAME "CC32xx"
#define SSID_NAME "DemoAP" /* AP SSID */
#define SECURITY_TYPE SL_WLAN_SEC_TYPE_WPA_WPA2 /* Security type could be SL_WLAN_SEC_TYPE_OPEN */
#define SECURITY_KEY "12345678" /* Password of the secured AP */
pthread_t udpThread = (pthread_t)NULL;
pthread_t spawn_thread = (pthread_t)NULL;
int32_t mode;
Display_Handle display;
extern void echoFxn(uint32_t arg0, uint32_t arg1);
extern int32_t ti_net_SlNet_initConfig();
/*
* ======== printError ========
*/
void printError(char *errString, int code)
{
Display_printf(display, 0, 0, "Error! code = %d, Description = %s\n", code,
errString);
while(1);
}
/*!
\brief SimpleLinkNetAppEventHandler
This handler gets called whenever a Netapp event is reported
by the host driver / NWP. Here user can implement he's own logic
for any of these events. This handler is used by 'network_terminal'
application to show case the following scenarios:
1. Handling IPv4 / IPv6 IP address acquisition.
2. Handling IPv4 / IPv6 IP address Dropping.
\param pNetAppEvent - pointer to Netapp event data.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 5.7
*/
void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
{
int32_t status = 0;
pthread_attr_t pAttrs;
struct sched_param priParam;
if(pNetAppEvent == NULL)
{
return;
}
switch(pNetAppEvent->Id)
{
case SL_NETAPP_EVENT_IPV4_ACQUIRED:
case SL_NETAPP_EVENT_IPV6_ACQUIRED:
/* Initialize SlNetSock layer with CC3x20 interface */
status = ti_net_SlNet_initConfig();
if(0 != status)
{
Display_printf(display, 0, 0, "Failed to initialize SlNetSock\n\r");
}
if(mode != ROLE_AP)
{
Display_printf(display, 0, 0,"[NETAPP EVENT] IP Acquired: IP=%d.%d.%d.%d , "
"Gateway=%d.%d.%d.%d\n\r",
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,3),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,2),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,1),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,0),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,3),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,2),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,1),
SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,0));
pthread_attr_init(&pAttrs);
priParam.sched_priority = 1;
status = pthread_attr_setschedparam(&pAttrs, &priParam);
status |= pthread_attr_setstacksize(&pAttrs, TASK_STACK_SIZE);
status = pthread_create(&udpThread, &pAttrs, (void *(*)(void *))echoFxn, (void*)UDPPORT);
if(status)
{
printError("Task create failed", status);
}
}
break;
default:
break;
}
}
/*!
\brief SimpleLinkFatalErrorEventHandler
This handler gets called whenever a socket event is reported
by the NWP / Host driver. After this routine is called, the user's
application must restart the device in order to recover.
\param slFatalErrorEvent - pointer to fatal error event.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 17.9.
*/
void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkNetAppRequestMemFreeEventHandler
This handler gets called whenever the NWP is done handling with
the buffer used in a NetApp request. This allows the use of
dynamic memory with these requests.
\param pNetAppRequest - Pointer to NetApp request structure.
\param pNetAppResponse - Pointer to NetApp request Response.
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 17.9.
\return void
*/
void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkNetAppRequestEventHandler
This handler gets called whenever a NetApp event is reported
by the NWP / Host driver. User can write he's logic to handle
the event here.
\param pNetAppRequest - Pointer to NetApp request structure.
\param pNetAppResponse - Pointer to NetApp request Response.
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 17.9.
\return void
*/
void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkHttpServerEventHandler
This handler gets called whenever a HTTP event is reported
by the NWP internal HTTP server.
\param pHttpEvent - pointer to http event data.
\param pHttpEvent - pointer to http response.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) chapter 9.
*/
void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *pHttpEvent,
SlNetAppHttpServerResponse_t *pHttpResponse)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkWlanEventHandler
This handler gets called whenever a WLAN event is reported
by the host driver / NWP. Here user can implement he's own logic
for any of these events. This handler is used by 'network_terminal'
application to show case the following scenarios:
1. Handling connection / Disconnection.
2. Handling Addition of station / removal.
3. RX filter match handler.
4. P2P connection establishment.
\param pWlanEvent - pointer to Wlan event data.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) sections 4.3.4, 4.4.5 and 4.5.5.
\sa cmdWlanConnectCallback, cmdEnableFilterCallback, cmdWlanDisconnectCallback,
cmdP2PModecallback.
*/
void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkGeneralEventHandler
This handler gets called whenever a general error is reported
by the NWP / Host driver. Since these errors are not fatal,
application can handle them.
\param pDevEvent - pointer to device error event.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 17.9.
*/
void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
{
/* Unused in this application */
}
/*!
\brief SimpleLinkSockEventHandler
This handler gets called whenever a socket event is reported
by the NWP / Host driver.
\param SlSockEvent_t - pointer to socket event data.
\return void
\note For more information, please refer to: user.h in the porting
folder of the host driver and the CC31xx/CC32xx NWP programmer's
guide (SWRU455) section 7.6.
*/
void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
{
/* Unused in this application */
}
void Connect(void)
{
SlWlanSecParams_t secParams = {0};
int16_t ret = 0;
secParams.Key = (signed char*)SECURITY_KEY;
secParams.KeyLen = strlen(SECURITY_KEY);
secParams.Type = SECURITY_TYPE;
Display_printf(display, 0, 0, "Connecting to : %s.\r\n",SSID_NAME);
ret = sl_WlanConnect((signed char*)SSID_NAME, strlen(SSID_NAME), 0, &secParams, 0);
if (ret)
{
printError("Connection failed", ret);
}
}
void mainThread(void *pvParameters)
{
int32_t status = 0;
pthread_attr_t pAttrs_spawn;
struct sched_param priParam;
SPI_init();
Display_init();
display = Display_open(Display_Type_UART, NULL);
if (display == NULL) {
/* Failed to open display driver */
while(1);
}
/* Start the SimpleLink Host */
pthread_attr_init(&pAttrs_spawn);
priParam.sched_priority = SPAWN_TASK_PRIORITY;
status = pthread_attr_setschedparam(&pAttrs_spawn, &priParam);
status |= pthread_attr_setstacksize(&pAttrs_spawn, TASK_STACK_SIZE);
status = pthread_create(&spawn_thread, &pAttrs_spawn, sl_Task, NULL);
if(status)
{
printError("Task create failed", status);
}
/* Turn NWP on - initialize the device*/
mode = sl_Start(0, 0, 0);
if (mode < 0)
{
Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, DEVICE_ERROR);
}
if(mode != ROLE_STA)
{
/* Set NWP role as STA */
mode = sl_WlanSetMode(ROLE_STA);
if (mode < 0)
{
Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, WLAN_ERROR);
}
/* For changes to take affect, we restart the NWP */
status = sl_Stop(SL_STOP_TIMEOUT);
if (status < 0)
{
Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, status, DEVICE_ERROR);
}
mode = sl_Start(0, 0, 0);
if (mode < 0)
{
Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, DEVICE_ERROR);
}
}
if(mode != ROLE_STA)
{
printError("Failed to configure device to it's default state", mode);
}
Connect();
}
In main_freertos.c file, I did modifications as follows:
retc = xTaskCreate (mainThread, "mainThread1", THREADSTACKSIZE, NULL, 3, NULL);
In platform.c file, I did modifications as follows:
status = xTaskCreate(spawn_thread, "Task 2", 1000, sl_Task, 1, NULL);
Please let me know if you need any further input on this from my side.
Regards,
H C Trivedi