Maxim Integrated / Mbed OS MAXREFDES155#

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers spawn.c Source File

spawn.c

00001 /*
00002  * spawn.c - CC31xx/CC32xx Host Driver Implementation
00003  *
00004  * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 
00005  * 
00006  * 
00007  *  Redistribution and use in source and binary forms, with or without 
00008  *  modification, are permitted provided that the following conditions 
00009  *  are met:
00010  *
00011  *    Redistributions of source code must retain the above copyright 
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  *    Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the 
00016  *    documentation and/or other materials provided with the   
00017  *    distribution.
00018  *
00019  *    Neither the name of Texas Instruments Incorporated nor the names of
00020  *    its contributors may be used to endorse or promote products derived
00021  *    from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00027  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00028  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00029  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00032  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00033  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035 */
00036 
00037 
00038 
00039 /*****************************************************************************/
00040 /* Include files                                                             */
00041 /*****************************************************************************/
00042 #include "simplelink.h"
00043 #include "protocol.h"
00044 #include "driver.h"
00045 
00046 
00047 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
00048 
00049 #define _SL_MAX_INTERNAL_SPAWN_ENTRIES      10
00050 
00051 typedef struct _SlInternalSpawnEntry_t
00052 {
00053     _SlSpawnEntryFunc_t                 pEntry;
00054     void*                               pValue;
00055     struct _SlInternalSpawnEntry_t*     pNext;
00056 }_SlInternalSpawnEntry_t;
00057 
00058 typedef struct
00059 {
00060     _SlInternalSpawnEntry_t     SpawnEntries[_SL_MAX_INTERNAL_SPAWN_ENTRIES];
00061     _SlInternalSpawnEntry_t*    pFree;
00062     _SlInternalSpawnEntry_t*    pWaitForExe;
00063     _SlInternalSpawnEntry_t*    pLastInWaitList;
00064     _SlSyncObj_t                SyncObj;
00065     _SlLockObj_t                LockObj;
00066     _u8                         IrqWriteCnt;
00067     _u8                         IrqReadCnt;
00068     void*                       pIrqFuncValue;
00069 }_SlInternalSpawnCB_t;
00070 
00071 _SlInternalSpawnCB_t g_SlInternalSpawnCB;
00072 
00073 
00074 void _SlInternalSpawnTaskEntry() 
00075 {
00076     _i16                         i;
00077     _SlInternalSpawnEntry_t*    pEntry;
00078     _u8                         LastEntry;
00079 
00080     /* create and lock the locking object. lock in order to avoid race condition 
00081         on the first creation */
00082     sl_LockObjCreate(&g_SlInternalSpawnCB.LockObj,"SlSpawnProtect");
00083     sl_LockObjLock(&g_SlInternalSpawnCB.LockObj,SL_OS_NO_WAIT);
00084 
00085     /* create and clear the sync object */
00086     sl_SyncObjCreate(&g_SlInternalSpawnCB.SyncObj,"SlSpawnSync");
00087     sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_NO_WAIT);
00088 
00089     g_SlInternalSpawnCB.pFree = &g_SlInternalSpawnCB.SpawnEntries[0];
00090     g_SlInternalSpawnCB.pWaitForExe = NULL;
00091     g_SlInternalSpawnCB.pLastInWaitList = NULL;
00092 
00093     /* create the link list between the entries */
00094     for (i=0 ; i<_SL_MAX_INTERNAL_SPAWN_ENTRIES - 1 ; i++)
00095     {
00096         g_SlInternalSpawnCB.SpawnEntries[i].pNext = &g_SlInternalSpawnCB.SpawnEntries[i+1];
00097         g_SlInternalSpawnCB.SpawnEntries[i].pEntry = NULL;
00098     }
00099     g_SlInternalSpawnCB.SpawnEntries[i].pNext = NULL;
00100 
00101     g_SlInternalSpawnCB.IrqWriteCnt =0;
00102     g_SlInternalSpawnCB.IrqReadCnt = 0;
00103     g_SlInternalSpawnCB.pIrqFuncValue = NULL;
00104 
00105     SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
00106 
00107     /* here we ready to execute entries */
00108 
00109     while (TRUE)
00110     {
00111         sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_WAIT_FOREVER);
00112 
00113         /* handle IRQ requests */
00114         while (g_SlInternalSpawnCB.IrqWriteCnt != g_SlInternalSpawnCB.IrqReadCnt)
00115         {
00116             /* handle the ones that came from ISR context*/
00117             _SlDrvMsgReadSpawnCtx(g_SlInternalSpawnCB.pIrqFuncValue);
00118             g_SlInternalSpawnCB.IrqReadCnt++;
00119         }
00120 
00121         /* go over all entries that already waiting for execution */
00122         LastEntry = FALSE;
00123 
00124         do
00125         {
00126             /* get entry to execute */
00127             SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
00128 
00129             pEntry = g_SlInternalSpawnCB.pWaitForExe;
00130             if ( NULL == pEntry )
00131             {
00132                SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
00133                break;
00134             }
00135             g_SlInternalSpawnCB.pWaitForExe = pEntry->pNext;
00136             if (pEntry == g_SlInternalSpawnCB.pLastInWaitList)
00137             {
00138                 g_SlInternalSpawnCB.pLastInWaitList = NULL;
00139                 LastEntry = TRUE;
00140             }
00141 
00142             SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
00143 
00144             /* pEntry could be null in case that the sync was already set by some
00145                of the entries during execution of earlier entry */
00146             if (NULL != pEntry)
00147             {
00148                 pEntry->pEntry(pEntry->pValue);
00149                 /* free the entry */
00150 
00151                 SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
00152                 
00153                 pEntry->pNext = g_SlInternalSpawnCB.pFree;
00154                 g_SlInternalSpawnCB.pFree = pEntry;
00155 
00156 
00157                 if (NULL != g_SlInternalSpawnCB.pWaitForExe)
00158                 {
00159                     /* new entry received meanwhile */
00160                     LastEntry = FALSE;
00161                 }
00162 
00163                 SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
00164 
00165             }
00166 
00167         }while (!LastEntry);
00168     }
00169 }
00170 
00171 
00172 _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags)
00173 {
00174     _i16                         Res = 0;
00175     _SlInternalSpawnEntry_t*    pSpawnEntry;
00176 
00177 
00178     /*  Increment the counter that specifies that async event has recived 
00179         from interrupt context and should be handled by the internal spawn task */
00180     if (flags & SL_SPAWN_FLAG_FROM_SL_IRQ_HANDLER)
00181     {
00182         g_SlInternalSpawnCB.IrqWriteCnt++;
00183         g_SlInternalSpawnCB.pIrqFuncValue = pValue;
00184         SL_DRV_SYNC_OBJ_SIGNAL(&g_SlInternalSpawnCB.SyncObj);
00185         return Res;
00186     }
00187 
00188 
00189     if (NULL == pEntry || (g_SlInternalSpawnCB.pFree == NULL))
00190     {
00191         Res = -1;
00192     }
00193     else
00194     {
00195         SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
00196 
00197         pSpawnEntry = g_SlInternalSpawnCB.pFree;
00198         g_SlInternalSpawnCB.pFree = pSpawnEntry->pNext;
00199 
00200         pSpawnEntry->pEntry = pEntry;
00201         pSpawnEntry->pValue = pValue;
00202         pSpawnEntry->pNext = NULL;
00203 
00204         if (NULL == g_SlInternalSpawnCB.pWaitForExe)
00205         {
00206             g_SlInternalSpawnCB.pWaitForExe = pSpawnEntry;
00207             g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry;
00208         }
00209         else
00210         {
00211             g_SlInternalSpawnCB.pLastInWaitList->pNext = pSpawnEntry;
00212             g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry;
00213         }
00214 
00215         SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
00216         
00217         /* this sync is called after releasing the lock object to avoid unnecessary context switches */
00218         SL_DRV_SYNC_OBJ_SIGNAL(&g_SlInternalSpawnCB.SyncObj);
00219     }
00220 
00221     return Res;
00222 }
00223 
00224 
00225 
00226 
00227 
00228 #endif