This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3120MOD: sl_Send() does not block properly

Part Number: CC3120MOD
Other Parts Discussed in Thread: CC3120, CC31XXEMUBOOST


I want to send a burst of three messages in transceiver mode using sl_Send(). However, rapidly calling it only lets the first one through even though sl_Send() correctly returns the number of bytes sent for all three. After this, slcb_SockEvtHdlr fires with

{Event = 1, SocketAsyncEvent = {SockTxFailData = {Status = -9, Sd = 0 '\000', Padding = 17 '\021'}, SockAsyn cData = {Sd = 247 '\367', Type = 255 '\377', Val = 4352, pExtraInfo = '\000' }}}

where Event = 1 corresponds to SockTxFailData according to sl_socket.h. What does status = -9 mean?

If I add a delay between the sl_Send()s all three messages show up in Wireshark.

Here is the code I'm running

sl_Start(0, 0, 0); 

i16 status;

status = sl_WlanPolicySet( SL_WLAN_POLICY_CONNECTION, SL_WLAN_CONNECTION_POLICY(0, 0, 0, 0), NULL, 0);

if (status) { debug_printf("Failed to set WLAN connection policy\r\n"); }

status = sl_WlanDisconnect();
if (status) { debug_printf("WLAN already disconnected\r\n"); }

short socket = sl_Socket(SL_AF_RF, SL_SOCK_RAW, 1);
if (socket < 0) { debug_printf("Failed to created RAW socket\r\n"); }

for (u8 i = 0; i < 3; ++i) {
// Modify the message slightly here

short status = sl_Send(socket, message->buffer, message->length, SL_WLAN_RAW_RF_TX_PARAMS(1, SL_WLAN_RATE_6M, 13, SL_WLAN_LONG_PREAMBLE));
if (status != message->length) { debug_printf("Error when sending raw message: %d\r\n", (int) status); }

// for (u32 j = 0; j < 1000000; ++j);


The only debug_printf that shows up is "WLAN is already disconnected". If I uncomment the inner for loop all messages are sent.

It seems sl_Send() only blocks until data is sent from the host MCU to the CC3120, not until the CC3120 has actually sent it over the air. Thus, it is busy when I send it the second and third message.

I'm running this on an STM32L412 without any RTOS and my application is power sensitive. I want to send these messages as fast as possible then go back to sleep. Any help would be greatly appreciated.

  • Hi,

    It is strange.

    3 messages shouldn't cause any buffering issues within the device (what is the length that you are sending?) so i don't understand how the delay helps.

    Is this consistent?



  • Hi,

    The messages are 52 bytes each. It is consistent. I also consistently get two "tx failed"-events and since the first one goes through I assume they correspond to the second and third message. For the record I deviated from the documentation when porting the driver.

    1. I call sl_Task(NULL) in sl_SyncObjWait in a loop while waiting for the semaphore to be signaled. The driver would hang during initialization otherwise.

    2. All sl_LockObj* functions are no-ops since I only have one thread. Just to check I implemented a simple mutex represented as an integer where 1 == locked and 0 == unlocked, but it made no difference.

  • What do you mean by " The driver would hang during initialization otherwise"?

    Are you running a non-rtos example (from the SDK) an it hangs during initialization? 

    I'm not sure how your method works as sl_Task calls sl_SyncObjWait...

  • #define SEMAPHORE_OK (0)

    #define SEMAPHORE_FAILURE (-1)

    #define SEMAPHORE_TIMEOUT (-2)

    int sl_SyncObjWait(_SlSyncObj_t *self, uint32_t timeout) {

      u64 time_start = time_now(); // Time in milliseconds

      while (*self <= 0 && time_now() - time_start < timeout) {



      if (*self == 0) { return SEMAPHORE_TIMEOUT; }

      *self = *self > 0 ? *self - 1 : 0;

      return SEMAPHORE_OK;


    Here's my sl_SyncObjWait function. If I uncomment sl_Task(NULL) my code hangs at the while loop during sl_Start.

    Here's the relevant backtrace

    #2 0x08007ece in sl_SyncObjWait(self=0x20000ee4 , timeout=4294967295) at rest_of_path/lib/cc3120/src/porting/user.c:119 // This is the while loop line in the code above

    #3 0x08006c52 in _SlDrvSyncObjWaitForever(pSyncObj=0x20000ee4) at rest_of_path/lib/cc3120/src/driver.c:2782

    #4 0x08006e2e in _SlDrvWaitForInternalAsyncEvent(ObjIdx=0 '\000', Timeout=65535, Opcode=8) at rest_of_path/lib/cc3120/src/driver.c:2977

    #5 0x08003d9e in sl_Start(pIfHdl=0x0, pDevName=0x0, pInitCallBack=0x0) at rest_of_path/lib/cc3120/src/device.c:178

    #6 0x08000252 in wifi_send(message=0x20009cb8) at rest_of_path/wifi.c:13 // This is the function I outlined in my initial post

    Keep in mind that I pieced together sl_SyncObjWait mostly from trial and error. "Porting the Host Driver" from the cc3120 user guide only gives a superficial description of how the porting layer should work.

    After some layers of abstraction sl_Task ends up in _SlNonOsHandleSpawnTask in my copy of the driver. It does not call sl_SyncObjWait. The spawned task might call it, of course.

    I'm running the code I outlined in my initial post of this thread, not an example from the SDK

  • This seems ok.

    Do you have a reference platform where you can try your code in RTOS environment,

    I want to make sure the issue is with the specific command and not with the NORTOS or your porting.

    Have you tried calling sl_Task after every sl_Send?



  • Adding sl_Task after every send did not help. A colleague is working with the cc3220. I'll ask him to run the code on that one. Then we'll at least eliminate my porting as a cause for the error.

  • ok. i'll wait for his input then.

  • My colleague tried it now, and the code in the original post correctly sends 3 messages on his CC3220 no-rtos setup. So it seems there is something wrong with my porting. I have several questions

    1. I found the SL Driver in two places. Both in an SDK and in a "Wifi-plugin". Which is correct? Are they different?

    2. "Porting the Host Driver" in the user guide states that if I don't have an RTOS I don't have to implement the synchronization objects. Yet, if I remove the semaphore and mutex functions, the program won't compile. Are there any compiler options I have to set?

    3. I have left the lock object implementations empty since I only have one thread. Is this correct?

    4. The driver fails to compile unless I define a macro WAIT_NWP_SHUTDOWN_READY which I didn't find any documentation for. I have left it empty. What should it do? It's only used in sl_Stop so it won't affect this problem, but I'd like to correctly implement it.

    5. I have not done any firmware updates on the cc3120. Should I?

  • 1. The 2 instances are basically the same (the one from the CC32xx SDK is a newer and may include some bug fixes). The main differences are in the porting layers - one is build for CC32xx and the other (from the plugin) for MSP432.

    2. SL_PLATFORM_MULTI_THREADED should not be defined

    3. Please refer to the non-"SL_PLATFORM_MULTI_THREADED" code but i believe the lock is still needed (to protect between main execution thread and interrupt contexts.

     4. check in the reference code.

    5. Yes, you must update the service pack.

  • 1. Okay, I'll use the one from the SDK then

    2. It isn't

    3. Okay, I'll implement a proper mutex.

    4. Will do

    5. It turns out I need a CC31XXEMUBOOST board to do that. We've ordered some now. I'll get back to you once I've done the upgrade.

  • thanks for the update.

    I'll close this for now.

    Please open a new thread if you have further questions/issues.