view src/nucleus/erc.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*************************************************************************/
/*                                                                       */
/*               Copyright Mentor Graphics Corporation 2002              */
/*                         All Rights Reserved.                          */
/*                                                                       */
/* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS  */
/* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS   */
/* SUBJECT TO LICENSE TERMS.                                             */
/*                                                                       */
/*************************************************************************/

/*************************************************************************/
/*                                                                       */
/* FILE NAME                                               VERSION       */
/*                                                                       */
/*      erc.c                                          Nucleus PLUS 1.14 */
/*                                                                       */
/* COMPONENT                                                             */
/*                                                                       */
/*      ER - Error Management                                            */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This file contains the core routines for the Error management    */
/*      component.                                                       */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* FUNCTIONS                                                             */
/*                                                                       */
/*      ERC_System_Error                    System error function        */
/*      ERC_Assert                          System assertion routine     */
/*                                                                       */
/* DEPENDENCIES                                                          */
/*                                                                       */
/*      tc_defs.h                           Thread control definitions   */
/*      er_extr.h                           Error handling functions     */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified copyright notice,                       */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      04-17-1996      updated to version 1.2                           */
/*      03-24-1998      Released version 1.3.                            */
/*      11-24-1998      Added ERC_Assert routine.                        */
/*      03-26-1999      Released 1.11m (new release                      */
/*                        numbering scheme)                              */
/*      04-07-1999      Release 1.11mA                                   */
/*      04-17-2002      Released version 1.13m                           */
/*      11-07-2002      Released version 1.14                            */
/*************************************************************************/
#define         NU_SOURCE_FILE

#ifdef          NU_ERROR_STRING
#include        <stdio.h>                   /* Standard I/O functions    */
#endif
#include        "tc_defs.h"                 /* Thread control constants  */
#include        "er_extr.h"                 /* Error handling functions  */

#ifdef NU_DEBUG_MEMORY

#include        "er_defs.h"               /* Error management structures */
#include        "dm_extr.h"               /* Memory management           */
#include        "ncl\inc\string.h"        /* memcmp & memcpy functions   */
#include        "ncl\inc\nu_ncl.h"        /* memcmp & memcpy functions   */

extern NU_MEMORY_POOL  NU_DEBUG_POOL;
extern const UINT8 ERD_MemoryAllocationHead[];
extern const UINT8 ERD_MemoryAllocationFoot[];
extern ER_DEBUG_ALLOCATION *ERD_RecentAllocation;

extern UINT32 ERD_AllocationCount;
extern UINT32 ERD_AllocationSequenceCounter;
extern UINT32 ERD_TotalMemoryAllocated;
extern UINT32 ERD_TotalMemoryAllocations;
extern UINT32 ERD_MaxTotalMemoryAllocated;
extern UINT32 ERD_MaxTotalMemoryAllocations;

#endif /* NU_DEBUG_MEMORY */


/* Define external inner-component global data references.  */

extern  INT     ERD_Error_Code;

#ifdef          NU_ERROR_STRING
extern  CHAR    ERD_Error_String[];
#endif

#ifdef NU_DEBUG
extern UNSIGNED ERD_Assert_Count;
#endif


/* Define direct access to a thread component variable.  */

extern  VOID   *TCD_Current_Thread;

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_System_Error                                                 */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function processes system errors detected by various        */
/*      system components.  Typically an error of this type is           */
/*      considered fatal.                                                */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Various Components                                               */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      error_code                          Code of detected system error*/
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*                                                                       */
/*************************************************************************/
VOID  ERC_System_Error(INT error_code)
{
#ifdef          NU_ERROR_STRING
INT     i;
CHAR   *pointer;
CHAR    name[NU_MAX_NAME+1];
#endif

NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* First place the error code into the global variable.  */
    ERD_Error_Code =  error_code;

#ifdef          NU_ERROR_STRING
    /* Build string that corresponds to the error.  */
    switch(error_code)
    {

    case        NU_ERROR_CREATING_TIMER_HISR:

        /* Build string that indicates an error occurred creating the timer
           HISR.  */
        sprintf(ERD_Error_String,"%s\n", "Error Creating Timer HISR");
        break;

    case        NU_ERROR_CREATING_TIMER_TASK:

        /* Build string that indicates an error occurred creating the timer
           Task.  */
        sprintf(ERD_Error_String,"%s\n", "Error Creating Timer Task");
        break;

    case        NU_STACK_OVERFLOW:

        /* Build string that indicates a stack overflow occurred.  */
        name[NU_MAX_NAME] =  (CHAR) 0;
        pointer =  (((TC_TCB *) TCD_Current_Thread) -> tc_name);
        for (i = 0; i < NU_MAX_NAME; i++)
            name[i] =  *pointer++;
        sprintf(ERD_Error_String,"%s %s\n", "Stack Overflow in task/HISR: ",
                                                                        name);
        break;


    case        NU_UNHANDLED_INTERRUPT:

        /* Build string that indicates an error occurred because of an
           unhandled interrupt.  */
        sprintf(ERD_Error_String,"%s\n", "Unhandled interrupt error");
        break;
    }
#endif

    /* This function cannot return, since the error is fatal.  */
    while(1)
    {
    }

    /* No need to return to user mode because of the infinite loop. */
    /* Returning to user mode will cause warnings with some compilers. */
}

#ifdef NU_DEBUG_MEMORY

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Memory_To_Debug                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function returns a pointer to the ER_DEBUG_ALLOCATION that  */
/*      contains the memory allocation specified by the caller (target). */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      ERC_Deallocate_Memory                                            */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      memcmp (CLIB_memcmp)                                             */
/*      ERC_System_Error                                                 */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      target                          memory allocation to find        */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      ER_DEBUG_ALLOCATION             ER_DEBUG_ALLOCATION that contains*/
/*                                        target.                        */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*************************************************************************/
static ER_DEBUG_ALLOCATION *ERC_Memory_To_Debug(VOID *target)
{
    INT dataOffset;
    ER_DEBUG_ALLOCATION *walk;
    ER_DEBUG_ALLOCATION *to_find;

    dataOffset = (INT)(((ER_DEBUG_ALLOCATION *)0)->data);
    to_find = (ER_DEBUG_ALLOCATION *)(((UNSIGNED_CHAR *)target) - dataOffset);

    /* Invalid pointer, report no match found */
    if((target == NULL) && (to_find == NULL))
        return(NULL);

    for (walk = ERD_RecentAllocation; ((walk != to_find) && (walk !=  NULL));
        walk = walk->prev);

    /* if no match was found */
    if (walk != NULL)
    {
        /* Has the "HEAD" or "FOOT" been disturbed by a rouge pointer? */
        if (memcmp((void *)ERD_MemoryAllocationHead,(void *)walk->head,4) != 0)
            ERC_System_Error(NU_MEMORY_CORRUPT);
        if (memcmp((void *)ERD_MemoryAllocationFoot,(void *)&(walk->data[walk->size]),4) != 0)
            ERC_System_Error(NU_MEMORY_CORRUPT);
    }

    return(walk);
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Remove_Debug_Allocation                                      */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function removes an ER_DEBUG_ALLOCATION from the linked list*/
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      ERC_Deallocate_Memory                                            */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      none                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      target                          ER_DEBUG_ALLOCATION to remove    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      STATUS                          status of the operation          */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*************************************************************************/
static STATUS ERC_Remove_Debug_Allocation(ER_DEBUG_ALLOCATION *target)
{
    ER_DEBUG_ALLOCATION *walk;

    if (target == NULL)
        return(NU_INVALID_POINTER);

    /* If the list is empty nothing can be removed! */
    if (ERD_RecentAllocation == NULL)
        return(NU_EMPTY_DEBUG_ALLOCATION_LIST);

    /* If there is only one item on the list. */
    if (ERD_RecentAllocation->prev == NULL)
    {
        /* If the only item on the list is the one to be removed...*/
        if (ERD_RecentAllocation == target)
        {
            ERD_RecentAllocation = NULL;
            return(NU_SUCCESS);
        }
        else
            return(NU_INVALID_DEBUG_ALLOCATION);
    }

    if (ERD_RecentAllocation == target)
    {
        ERD_RecentAllocation->prev = target->prev;
        return(NU_SUCCESS);
    }
    
    /* Walk the entire list until walk->prev is the target. */
    walk = ERD_RecentAllocation;
    while (NU_TRUE)
    {
        if (walk->prev == target)
            break;
        if (walk->prev == NULL)
            break;
        walk = walk->prev;
    }

    /* target is last item on the list */
    if (walk->prev == target)
    {
        walk->prev = target->prev;
        return(NU_SUCCESS);
    }
    return(NU_INVALID_DEBUG_ALLOCATION);
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Append_Debug_Allocation                                      */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function appends an ER_DEBUG_ALLOCATION to the linked list. */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      ERC_Allocate_Memory                                              */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      none                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      new_guy                         ER_DEBUG_ALLOCATION to append    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      STATUS                          status of the operation          */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*************************************************************************/
static STATUS ERC_Append_Debug_Allocation(ER_DEBUG_ALLOCATION *new_guy)
{

    /* Either this is the first ER_DEBUG_ALLOCATION ever to be appended
       or this is the first on a list that shrank to 0 element. */
    if (ERD_AllocationCount == 0)
    {
        ERD_RecentAllocation = new_guy;
        ERD_RecentAllocation->prev = NULL;
    }
    else
    {
        new_guy->prev = ERD_RecentAllocation;
        ERD_RecentAllocation = new_guy;
    }

    return(NU_SUCCESS);
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Allocate_Memory                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function tracks additional information regarding the memory */
/*      allocation                                                       */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      ERC_Append_Debug_Allocation                                      */
/*      DMCE_Allocate_Memory                                             */
/*      memcpy                                                           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      pool_ptr                            Memory pool pointer          */
/*      return_pointer                      Pointer to the destination   */
/*                                            memory pointer             */
/*      size                                Number of bytes requested    */
/*      suspend                             Suspension option if full    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          If service is successful     */
/*      NU_NO_MEMORY                        Memory not available         */
/*      NU_TIMEOUT                          If timeout on service        */
/*      NU_POOL_DELETED                     If memory pool deleted       */
/*                                            during suspension          */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*************************************************************************/
STATUS ERC_Allocate_Memory(NU_MEMORY_POOL *pool_ptr, VOID **ptr,
                           UNSIGNED size, UNSIGNED suspend, 
                           unsigned long line, const char* file)
{
    ER_DEBUG_ALLOCATION **debug_ptr;
    STATUS status = NU_SUCCESS;

    /* If the allocation is not from the pool specified in the 
       NU_DEBUG_POOL macro then allocate memory normally (no meta-data) */
    if(&NU_DEBUG_POOL != pool_ptr)
        return(DMCE_Allocate_Memory(pool_ptr, ptr, size, suspend));

    /* This call allocates memory for a structure that will contain the 
       users data and the meta-data used to find memory problems */
    status = DMCE_Allocate_Memory(pool_ptr, ptr,
        (sizeof(ER_DEBUG_ALLOCATION) + size + 4), suspend);
    if (status != NU_SUCCESS)
        return status;

    /* From here out, debug_ptr is used because it is typed.  In the end
       ptr will be set to point to debug_ptr->data, where the user will
       put the data. */
    debug_ptr = (ER_DEBUG_ALLOCATION **)ptr;

    /* Record file and line where the application made the allocation */
    (*debug_ptr)->line = line;
    (*debug_ptr)->file = file;

    /* Set "HEAD" and "FOOT" boundary markers */
    memcpy((*debug_ptr)->head,ERD_MemoryAllocationHead,4);
    memcpy(&((*debug_ptr)->data[size]),ERD_MemoryAllocationFoot,4);

    /* Record the size */
    (*debug_ptr)->size = size;

    /* This links debug_ptr to a linked list that holds all the
       ER_DEBUG_ALLOCATION structures. */
    ERC_Append_Debug_Allocation((*debug_ptr));

    (*debug_ptr)->AllocSequenceCounter = ERD_AllocationSequenceCounter++;

    ERD_TotalMemoryAllocated += size;
    ERD_TotalMemoryAllocations++;
    ERD_AllocationCount++;

    if (ERD_MaxTotalMemoryAllocated < ERD_TotalMemoryAllocated)
        ERD_MaxTotalMemoryAllocated = ERD_TotalMemoryAllocated;
    if (ERD_MaxTotalMemoryAllocations < ERD_TotalMemoryAllocations)
        ERD_MaxTotalMemoryAllocations = ERD_TotalMemoryAllocations;

    /* Return pointer to the data field of debug allocation by reference */
    (*ptr) = (*debug_ptr)->data;
   return(status);
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Deallocate_Memory                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function tracks additional information regarding the memory */
/*      deallocation.                                                    */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      ERC_Memory_To_Debug                                              */
/*      ERC_Remove_Debug_Allocation                                      */
/*      DMCE_Deallocate_Memory                                           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      ptr                                 Pointer to dynamic memory    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*      NU_INVALID_POINTER                  Returned when ptr is null or */
/*                                            when there is no           */
/*                                            corresponding              */
/*                                            ER_DEBUG_ALLOCATION        */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*************************************************************************/
STATUS ERC_Deallocate_Memory(VOID *ptr)
{
    ER_DEBUG_ALLOCATION *target;
    STATUS status;

    if (ptr == NULL)
        return(NU_INVALID_POINTER);

    /* Find the NU_DEBUG_ALLOCATION ptr refers to.  After this call, 
       (&(target->data) == ptr) or (target == NULL). */
    target = ERC_Memory_To_Debug(ptr);

    /* Remove target from the linked list of ER_DEBUG_ALLOCATIONs */
    status = ERC_Remove_Debug_Allocation(target);

    if ((status != 0) || (target == NULL))
        return(NU_INVALID_POINTER);
        
    /* Maintain status variables */
    ERD_TotalMemoryAllocated -= target->size;
    ERD_TotalMemoryAllocations--;
    ERD_AllocationCount--;

    return(DMCE_Deallocate_Memory(target));
}

#endif /* NU_DEBUG_MEMORY */

/**************************************************************************
  This routine should appear last in this file and must *NOT* use the
  NU_ASSERT macro.
**************************************************************************/

#ifdef NU_ASSERT                  /* Don't use NU_ASSERT past this point */
#undef NU_ASSERT
#define NU_ASSERT(ignore) ((void) 0)
#endif

#ifdef NU_ASSERT2
#undef NU_ASSERT2
#define NU_ASSERT2(ignore) ((void) 0)
#endif

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ERC_Assert                                                       */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This public routine is called when an assertion made by the      */
/*      NU_ASSERT (or NU_ASSERT2) macro fails.  By default, this routine */
/*      simply counts the number of failed assertions.  A breakpoint can */
/*      be set in the routine to observe failed assertions, or the       */
/*      routine can be customized to perform some action, such as        */
/*      printing the failed assertion as a message, etc.                 */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      NU_ASSERT macro                                                  */
/*      NU_ASSERT2 macro                                                 */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      test               Pointer to string of failed assertion test    */
/*      name               File name of file containing failed assertion */
/*      line               Location of failed assertion in above file    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*          NAME            DATE                    REMARKS              */
/*                                                                       */
/*      Todd C. Larsen    09-01-1998        Created initial revision     */
/*                                                                       */
/*************************************************************************/
#ifdef NU_DEBUG

void ERC_Assert(CHAR *test, CHAR *name, UNSIGNED line)
{
NU_SUPERV_USER_VARIABLES

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_ASSERT_ID, (UNSIGNED) test,
                        (UNSIGNED) name, line);

#endif

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Set breakpoint here to catch failed assertions. */
    ERD_Assert_Count += 1;

    /* Return to user mode */
    NU_USER_MODE();
}

#endif /* NU_DEBUG */