void bootstrap_exception_handler(void)
{
   const unsigned long wlStackSize = 4096;   // minimal (KB)
   static DALSYSEventHandle hEventStart;     // context for the error exception handler
   static DALSYSWorkLoopHandle hWorkLoop;    // context for the error exception handler

   char err_task_name[13];

   if ( sizeof(err_task_name) <= tms_utils_fmt(err_task_name, 12, "err_pd_ex_%d", qurt_getpid()) )
   {
     MSG(MSG_SSID_TMS, MSG_LEGACY_ERROR,"Failed to copy task name in err_task_name ");
   }

   if (DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_WORKLOOP_EVENT, &hEventStart, NULL))
   {
      ERR_FATAL("Exception Handler initialization failure",0,0,0);
   }
   if (DAL_SUCCESS != DALSYS_RegisterWorkLoopEx(err_task_name, wlStackSize, wlPriority, dwMaxNumEvents, &hWorkLoop, NULL))
   {
      ERR_FATAL("Exception Handler initialization failure",0,0,0);
   }
   if (DAL_SUCCESS != DALSYS_AddEventToWorkLoop(hWorkLoop, err_exception_task, NULL, hEventStart, NULL))
   {
      ERR_FATAL("Exception Handler initialization failure",0,0,0);
   }
   if (DAL_SUCCESS != DALSYS_EventCtrl(hEventStart, DALSYS_EVENT_CTRL_TRIGGER))
   {
      ERR_FATAL("Exception Handler initialization failure",0,0,0);
   }

}
void rcinit_dal_loop_worker_create(void)
{
   if (DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_WORKLOOP_EVENT, &rcinit_internal.hEventWorkLoop, NULL))
   {
      ERR_FATAL("worker event creation", 0, 0, 0);
   }
   if (DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_NORMAL, &rcinit_internal.hEventWorkLoopAck, NULL))
   {
      ERR_FATAL("worker create event initfn", 0, 0, 0);
   }
   if (DAL_SUCCESS != DALSYS_RegisterWorkLoopEx("rcworker", rcinit_lookup_stksz("rcinit"), rcinit_lookup_prio("rcinit"), dwMaxNumEvents, &rcinit_internal.hWorkLoop, NULL))
   {
      ERR_FATAL("worker work loop registration", 0, 0, 0);
   }
   if (DAL_SUCCESS != DALSYS_AddEventToWorkLoop(rcinit_internal.hWorkLoop, rcworker, RCINIT_NULL, rcinit_internal.hEventWorkLoop, NULL))
   {
      ERR_FATAL("worker work loop event addition", 0, 0, 0);
   }
}
/*==================================================================================================

FUNCTION: Uart_busy_wait

DESCRIPTION:

==================================================================================================*/
void Uart_busy_wait(uint32 usecs)
{
   DALSYSEventHandle timer_event = NULL;
   uint32 triggered_event;
   DALResult result;

   result = DALSYS_EventCreate(DALSYS_EVENT_ATTR_TIMEOUT_EVENT | DALSYS_EVENT_ATTR_NON_DEFERRED,
                               &timer_event, NULL);
   if (result != DAL_SUCCESS)
   {
      UART_LOG_0(ERROR,"Unable to create timer event");
      goto exit;
   }

   result = DALSYS_EventMultipleWait(&timer_event, 1, usecs , &triggered_event);
   if (result != DAL_ERROR_TIMEOUT)
   {
      UART_LOG_0(ERROR,"DALSYS_EventMultipleWait failed.");
      goto exit;
   }

exit:
   if (timer_event) { DALSYS_DestroyObject(timer_event); }
}
AUDIO_FTM_STS_T
audio_ftm_toneplay_attach
(
    void *pParam,                                 /* Input: parameters  */
    AUDIO_FTM_DRIVER_HANDLE_T *pDriverHdl        /* Output: driver handle */
)
{
  /************* Context creation ***********/

  Aud_FTM_DevCtxt_T *pDeviceCtxt;
  Aud_FTM_DrvCtxt_T *pDriverCtxt;

    Aud_FTM_HW_INIT_PARAM_T hw_param;
    int16 freq1,freq2, sampling_freq;

    AUDIO_FTM_STS_T sts;

    if (g_bDriverInitialized)
  {
      DALSYS_Log_Err("%s: error: already initialized\n", __func__);
        return  AUDIO_FTM_ERROR;    //  already inited,
  }

  DALSYS_Log_Info("Attach TonePlay Driver\n");

    /****************** create context object ******************/

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DevCtxt_T), (void **)&pDeviceCtxt)) ||
        (pDeviceCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDeviceCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DrvCtxt_T), (void **)&pDriverCtxt)) ||
        (pDriverCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
                DALSYS_Free(pDeviceCtxt);
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDriverCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

    DALSYS_atomic_init(&pDriverCtxt->dwOpenCount);
    pDriverCtxt->pDevCtxt=pDeviceCtxt;
    pDeviceCtxt->pDrvCtxt=pDriverCtxt;

  /************* Create Critical Section ***********/

    if(DAL_SUCCESS != DALSYS_SyncCreate(DALSYS_SYNC_ATTR_RESOURCE,
        &(pDriverCtxt->hClientSync),
        NULL))
    {
      DALSYS_Log_Err("hClientSync creation fail\n");
        return AUDIO_FTM_ERROR;
    }

   if(DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_WORKLOOP_EVENT,       //Not used for work loops
                              &(pDriverCtxt->hReq_Data_Event),          //Return event handle
                              NULL))
   {
    DALSYS_Log_Err("%s: failed to create event\n", __func__);
    DALSYS_SyncLeave(pDriverCtxt->hClientSync);
    DALSYS_Free(pDriverCtxt->hClientSync);
    return AUDIO_FTM_ERROR;
   }

    /*************  hardware initialization ***********/

   DALSYS_memcpy((uint8*)&(pDriverCtxt->client_param),
                  (uint8*)pParam, sizeof(AUD_FTM_TONE_PLAY_PARAM_T));

   hw_param.inpath=AUDIO_FTM_IN_INVALID;
   hw_param.outpath=pDriverCtxt->client_param.path.outpath;
   hw_param.rate=AUDIO_FTM_PCM_RATE_8K;
   hw_param.width=AUDIO_FTM_BIT_WIDTH_16;
   hw_param.channel=AUDIO_FTM_CHN_1;
   hw_param.gain=pDriverCtxt->client_param.gain;
     hw_param.bLoopbackCase=FALSE;

   sts=aud_ftm_hw_init(pDeviceCtxt, &hw_param);
   if(sts != AUDIO_FTM_SUCCESS) {
      DALSYS_Log_Err("%s: failed to init hw\n", __func__);
        return AUDIO_FTM_ERROR;
   }

      /* Tone generator init */

    freq1=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_low;
    freq2=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_hi;
    sampling_freq=8000;

    audio_ftm_dtmf_tone_init(&(pDriverCtxt->dtmfGen),freq1,freq2,sampling_freq);
    pDriverCtxt->nDTMF_Gain = vol_map[3];

    /***** end of Init *****/

        pDriverCtxt->bOpened=FALSE;
      g_bDriverInitialized=TRUE;
    *pDriverHdl=(AUDIO_FTM_DRIVER_HANDLE_T)pDriverCtxt;

      return AUDIO_FTM_SUCCESS;

}
/*===========================================================================

 FUNCTION rcinit_initfn_spawn_task

 DESCRIPTION
 required wrapper for an init function to spawn a task (very specialized edge
 case found during sequence group 0, this should be the exception)

 DEPENDENCIES
 Requires existing RCINIT task database information where the task entry
 point is NULL. The static data is preallocated, and this call binds the
 entry point to the context and starts it. Edge case; only allowed from
 Group 0 initfn processing. all other use cases are not supported and
 are considered a bug.

 RETURN VALUE
 none

 SIDE EFFECTS
 task must call rcinit_handshake_startup(); else startup process will block
 as designed

 ===========================================================================*/
void rcinit_initfn_spawn_task(RCINIT_INFO info_p, void* entry)
{
   boolean started = FALSE;
   rcinit_info_t* rcinit_p = (rcinit_info_t*)info_p;

   if (RCINIT_NULL != rcinit_p &&
       RCINIT_GROUP_0 == rcinit_lookup_group(rcinit_p->name) &&                  // must be in group 0 (only)
       RCINIT_GROUP_0 == rcinit_internal.group_curr &&                           // processing group 0 (only)
       rcinit_process_group_init_fn == rcinit_internal.process_state &&          // processing initfns (only)
       RCINIT_NULL == rcinit_p->entry &&                                         // must not have an entry (specialized)
       RCINIT_NULL != entry)                                                     // must have an entry point argument
   {
      // DAL Event Objects Are Protected on Context Allowed to Wait (Create/Wait/Destroy)
      if (DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_NORMAL, &rcinit_internal.hEventInitFnSpawn, NULL))
      {
         ERR_FATAL("initfnspawn event", 0, 0, 0);
      }

      if (RCINIT_NULL != rcinit_p->handle && RCINIT_ENTRY_NONE != rcinit_p->handle->entry)
      {
         if (RCINIT_TASK_DALTASK == rcinit_p->type)
         {
            rcinit_internal_start_daltask(rcinit_p, entry);                      // launches task and fills in overhead

            started = TRUE;
         }

         else if (RCINIT_TASK_POSIX == rcinit_p->type)
         {
            if (RCINIT_STACK_NULL == rcinit_p->handle->stack)
            {
               rcinit_p->handle->stack = (rcinit_stack_p)stack_base_pad(rcinit_internal_malloc(stack_base_pad(rcinit_p->stksz)));
            }

            rcinit_internal_start_posix(rcinit_p, entry);                        // launches task and fills in overhead

            started = TRUE;
         }

         else if (RCINIT_TASK_QURTTASK == rcinit_p->type)
         {
            if (RCINIT_STACK_NULL == rcinit_p->handle->stack)
            {
               rcinit_p->handle->stack = (rcinit_stack_p)stack_base_pad(rcinit_internal_malloc(stack_base_pad(rcinit_p->stksz)));
            }

            rcinit_internal_start_qurttask(rcinit_p, entry);                     // launches task and fills in overhead

            started = TRUE;
         }

         else if (RCINIT_TASK_REXTASK == rcinit_p->type || RCINIT_TASK_LEGACY == rcinit_p->type)
         {
            if (RCINIT_STACK_NULL == rcinit_p->handle->stack)
            {
               rcinit_p->handle->stack = (rcinit_stack_p)stack_base_pad(rcinit_internal_malloc(stack_base_pad(rcinit_p->stksz)));
            }

            rcinit_internal_start_rextask(rcinit_p, entry);                      // launches task and fills in overhead

            started = TRUE;
         }
      }

      // STALLING HERE?

      // BLOCKING HERE OCCURS UNTIL THE SINGLE TASK STARTED PERFORMS ITS HANDSHAKE.
      // THIS IS THE NORMAL MECHANISM. CHECK WITH THE TECH AREA OWNING THE CONTEXT
      // WHEN BLOCKING DURATION BECOMES EXCESSIVE WAITING FOR THE HANDSHAKE.

      if (TRUE == started)
      {
         // DAL Event Objects Are Protected on Context Allowed to Wait (Create/Wait/Destroy)
         if (DAL_SUCCESS != DALSYS_EventWait(rcinit_internal.hEventInitFnSpawn))
         {
            ERR_FATAL("initfnspawn event", 0, 0, 0);
         }
      }
      // DAL Event Objects Are Protected on Context Allowed to Wait (Create/Wait/Destroy)
      if (DAL_SUCCESS != DALSYS_DestroyObject(rcinit_internal.hEventInitFnSpawn))
      {
         ERR_FATAL("initfnspawn event", 0, 0, 0);
      }
   }
   else
   {
      ERR_FATAL("client does not meet requirements", 0, 0, 0);
   }
}