Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MaximInterface
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
Generated on Tue Jul 12 2022 12:06:49 by
1.7.2