FreeCalypso > hg > fc-magnetite
view src/g23m-gsm/dl/dl_trace.c @ 632:d968a3216ba0
new tangomdm build target
TCS211/Magnetite built for target leonardo runs just fine on the Tango-based
Caramel board, but a more proper tangomdm build target is preferable in order
to better market these Tango modems to prospective commercial customers. The
only differences are in GPIO and MCSI config:
* MCSI is enabled in the tangomdm build config.
* GPIO 1 is loudspeaker amplifier control on Leonardo, but on Tango platforms
it can be used for anything. On Caramel boards this GPIO should be
configured as an output driving high.
* GPIO 2 needs to be configured as Calypso input on Leonardo, but on Tango
platforms it can be used for anything. On Caramel boards this GPIO should be
configured as an output, either high or low is OK.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 04 Jan 2020 19:27:41 +0000 |
parents | 27a4235405c6 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This Modul defines the offline trace functions | for the component DL of the mobile station. +----------------------------------------------------------------------------- */ #ifndef DL_TRACE_C #define DL_TRACE_C #define ENTITY_DL /*==== INCLUDES ===================================================*/ #include "typedefs.h" #include <string.h> #include "vsi.h" #include "pconst.cdg" #include "custom.h" #include "gsm.h" #include "mon_dl.h" #include "prim.h" #include "pei.h" #include "tok.h" #include "ccdapi.h" #include "dl.h" /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ #if defined(DL_TRACE_ENABLED) #ifdef OPTION_MULTITHREAD #define TRACE_TYPE _ENTITY_PREFIXED(TRACE_TYPE) #define CHANNEL _ENTITY_PREFIXED(CHANNEL) #define STATES _ENTITY_PREFIXED(STATES) #endif /* OPTION_MULTITHREAD */ LOCAL const char* const STATES[] = { "INVALID", "DISABLED", "IDLE_DL", "SUSPENDED", "AWAITING_ESTABLISHMENT", "MULTI_FRAME_ESTABLISHED", "TIMER_RECOVERY", "AWAITING_RELEASE" }; LOCAL const char* const TRACE_TYPE[] = { "UL", "DL", "Ev", "St", "PL", "RR" }; LOCAL const char* const CH_TYPE[] = { " ", "SA", "SD", "FH", "FF", "CC", "BC", "PC", "PE", "CB", "BE" }; LOCAL const char SAPI_TYPE[] = { '0', '1', '2', '3', ' '}; LOCAL void array2hex (UBYTE *inarray, char *outarray, int size); #if !defined(DL_IMMEDIATE_TRACE) /*==== TEST TRACE ===================================================*/ #define TEST_ENTITY_DL /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ /* * The Data Link Layer Trace is a cyclic buffer for * debugging layer 2 problems. * * The buffer will be initialized at startup and will * be filled by the function dl_trace() until it is full. * The size of the buffer is IDLE_TRACE_SIZE. * * The content is * * trace_type (uplink, downlink, event state, alr_event, rr_event) * Channel Type (SACCH, SDDCH, FACCH) * real system clock * State (DL states) * pending disc request * data (layer frame, eevnt strings, state) * * During IDLE mode (triggered by RX_PERIODIC_IND in ALR/TIL_main.c) * an output is written to as SYST trace. * (IDLE_TRACE_MAX_READED traces each trigger) */ #define IDLE_TRACE_SIZE 512 #define IDLE_TRACE_MAX_READED 16 #if (((IDLE_TRACE_SIZE-1) & (~IDLE_TRACE_SIZE)) == (IDLE_TRACE_SIZE-1)) #define POWER_OF_2 #pragma message("IDLE_TRACE_SIZE is power of 2") #else #pragma message("IDLE_TRACE_SIZE is NOT power of 2") #endif typedef struct { UBYTE trace_type; UBYTE ch_type; UBYTE sapi; T_TIME sysClock; UBYTE disc_request; UBYTE state; UBYTE data [MAX_L2_FRAME_SIZE]; } T_IDLE_TRACE_DATA; #ifdef OPTION_MULTITHREAD #define IDLE_Trace_buffer _ENTITY_PREFIXED(IDLE_Trace_buffer) #define IDLE_Trace_write_index _ENTITY_PREFIXED(IDLE_Trace_write_index) #define IDLE_Trace_read_index _ENTITY_PREFIXED(IDLE_Trace_read_index) #endif /* OPTION_MULTITHREAD */ GLOBAL T_IDLE_TRACE_DATA IDLE_Trace_buffer [IDLE_TRACE_SIZE]; GLOBAL USHORT IDLE_Trace_write_index = 0; GLOBAL USHORT IDLE_Trace_read_index = 0; LOCAL T_HANDLE sem_DL_TRC; GLOBAL void dl_trace_init (void) { sem_DL_TRC = vsi_s_open (VSI_CALLER "DL_IDLE_TRACE",1); if (sem_DL_TRC NEQ VSI_ERROR) dl_trace_clear (0); else SYST_TRACE ("DL:canīt open semaphore \"DL_IDLE_TRACE\""); } GLOBAL void dl_trace_exit (void) { if (sem_DL_TRC NEQ VSI_ERROR) vsi_s_close (VSI_CALLER sem_DL_TRC); } GLOBAL void dl_trace_clear () { dl_trace_read_all (0); /* first, get all remaining traces (if exists) */ ENTER_CRITICAL_SECTION (sem_DL_TRC); IDLE_Trace_write_index = IDLE_Trace_read_index = 0; LEAVE_CRITICAL_SECTION (sem_DL_TRC); TRACE_EVENT ("offline trace reset"); DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, 0, "offline trace reset"); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_trace (UCHAR trace_type, UCHAR channel, UCHAR ch_type, UCHAR* data) { T_IDLE_TRACE_DATA* trace_data; USHORT write_index1, write_index2;/* trace_size must not be greater than 2 */ UBYTE trace_size; if (data) { #if defined (DISABLE_MEASREPORT_TRACE) if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[2] EQ 0x01) AND (data[3] EQ 0x03) AND (data[4] EQ 0x49)) return; #endif /* DISABLE_MEASREPORT_TRACE */ #if defined (DISABLE_EMPTY_UI) if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[3] EQ 0x03) AND (data[4] EQ 0x01)) return; else if ( (data[1] EQ 0x03) AND (data[2] EQ 0x01)) return; } #endif /* DISABLE_EMPTY_UI */ } TEST_SEMAPHORE (sem_DL_TRC); ENTER_CRITICAL_SECTION(sem_DL_TRC); trace_size = 1; if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT)) { if (data AND strlen ((char *)data) >= 23) trace_size = 2; } #if defined(POWER_OF_2) write_index1 = (IDLE_Trace_write_index + 1) & (IDLE_TRACE_SIZE - 1); /* if IDLE_TRACE_SIZE power of 2 */ write_index2 = (IDLE_Trace_write_index + trace_size) & (IDLE_TRACE_SIZE - 1); /* if IDLE_TRACE_SIZE power of 2 */ #else write_index1 = (IDLE_Trace_write_index + 1) % IDLE_TRACE_SIZE; /* if IDLE_TRACE_SIZE not power of 2 */ write_index2 = (IDLE_Trace_write_index + trace_size) % IDLE_TRACE_SIZE; /* if IDLE_TRACE_SIZE not power of 2 */ #endif /* POWER_OF_2 */ if ((write_index1 NEQ IDLE_Trace_read_index) AND (write_index2 NEQ IDLE_Trace_read_index)) { /* buffer is not full */ trace_data = &IDLE_Trace_buffer[IDLE_Trace_write_index]; trace_data->trace_type = trace_type; if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT)) { trace_data->state = trace_size; } else { GET_INSTANCE_DATA; trace_data->ch_type = ch_type; switch (channel) { case C_SACCH0: case C_DCCH0: trace_data->disc_request = dl_data->dcch0_disc_request; trace_data->state = dl_data->state [C_DCCH0]; trace_data->sapi = PS_SAPI_0; break; case C_DCCH3: trace_data->disc_request = dl_data->dcch3_disc_request; trace_data->state = dl_data->state [C_DCCH3]; trace_data->sapi = PS_SAPI_3; break; default: trace_data->disc_request = 0; trace_data->state = 0; trace_data->sapi = NOT_PRESENT_8BIT; break; } } vsi_t_time (VSI_CALLER &trace_data->sysClock); if (data) { memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE); if ((trace_type NEQ TRACE_UPLINK) AND (trace_type NEQ TRACE_DOWNLINK)) { trace_data->data[MAX_L2_FRAME_SIZE-1] = 0; } if (trace_size EQ 2) { if (IDLE_Trace_write_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */ trace_data = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */ else trace_data++; memcpy (trace_data->data, data+MAX_L2_FRAME_SIZE-1, MAX_L2_FRAME_SIZE-1); trace_data->data[MAX_L2_FRAME_SIZE-1] = 0; } } IDLE_Trace_write_index = write_index2; }/* endif buffer is not full */ LEAVE_CRITICAL_SECTION (sem_DL_TRC); #if defined(_SIMULATION_) dl_trace_read (0); #endif /* _SIMULATION_ */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace_read | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_trace_read_all () { USHORT write_index, read_index; do { dl_trace_read (); ENTER_CRITICAL_SECTION (sem_DL_TRC); write_index = IDLE_Trace_write_index; read_index = IDLE_Trace_read_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); } while (read_index NEQ write_index); } GLOBAL void dl_trace_read () { T_IDLE_TRACE_DATA* trace_data; USHORT write_index, read_index, left; UBYTE trace_size; static char buffer[80]; UBYTE j, o, readed = 0; TEST_SEMAPHORE (sem_DL_TRC); ENTER_CRITICAL_SECTION (sem_DL_TRC); write_index = IDLE_Trace_write_index; read_index = IDLE_Trace_read_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); if (read_index EQ write_index) { #if defined (_TARGET_) AND !defined( GPRS ) AND defined(FF_GTI) sleep_mode (); #endif /* _TARGET_ AND !GPRS AND !FF_GTI */ return; } while (read_index NEQ write_index) { ENTER_CRITICAL_SECTION (sem_DL_TRC); trace_data = &IDLE_Trace_buffer[read_index]; LEAVE_CRITICAL_SECTION (sem_DL_TRC); #if defined(POWER_OF_2) left = (write_index - read_index - 1) & (IDLE_TRACE_SIZE-1); #else left = (IDLE_TRACE_SIZE + write_index - read_index - 1) % IDLE_TRACE_SIZE; #endif /* POWER_OF_2 */ if (trace_data->ch_type > ELEMENTS(CH_TYPE)) trace_data->ch_type = 0; if (trace_data->sapi >= ELEMENTS (SAPI_TYPE)) trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1; trace_size = 1;/* default */ switch (trace_data->trace_type) { case TRACE_UPLINK: case TRACE_DOWNLINK: sprintf (buffer, "[%03d]:%07lu %c%d %s %s ", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, TRACE_TYPE[trace_data->trace_type], CH_TYPE[trace_data->ch_type]); o = strlen (buffer); array2hex (trace_data->data, buffer+o, 23); break; case TRACE_DL_EVENT: sprintf (buffer, "[%03d]:%07lu %c%d Ev %s%c %s", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[trace_data->ch_type], SAPI_TYPE[trace_data->sapi], trace_data->data); break; case TRACE_PL_EVENT: case TRACE_RR_EVENT: trace_size = trace_data->state; if (trace_size EQ 2) { T_IDLE_TRACE_DATA *trace_data2; if (read_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */ trace_data2 = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */ else trace_data2 = trace_data+1; sprintf (buffer, "[%03d]:%07lu %d Ev %s %s%s", left, trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_data->trace_type], trace_data->data, trace_data2->data); } else { sprintf (buffer, "[%03d]:%07lu %d Ev %s %s", left, trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_data->trace_type], trace_data->data); } break; case TRACE_CHSTATE: sprintf (buffer, "[%03d]:%07lu %c%d ST %s%c state=%s", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[trace_data->ch_type], SAPI_TYPE[trace_data->sapi], STATES[trace_data->state]); break; default: buffer[0] = 0; break; } if (buffer[0]) { SYST_TRACE (buffer); } else { SYST_TRACE ("dl_trace_read() failed"); } ENTER_CRITICAL_SECTION (sem_DL_TRC); trace_data->sysClock = 0; /* readed */ IDLE_Trace_read_index += trace_size; #if defined(POWER_OF_2) IDLE_Trace_read_index &= (IDLE_TRACE_SIZE-1);/* if power of 2 */ #else IDLE_Trace_read_index %= IDLE_TRACE_SIZE; /* if not power of 2 */ #endif /* POWER_OF_2 */ read_index = IDLE_Trace_read_index; write_index = IDLE_Trace_write_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); if (readed++ >= IDLE_TRACE_MAX_READED) break; }/* endwhile */ } #else /* DL_IMMEDIATE_TRACE */ #define IMM_TRACE_SIZE 2 typedef struct { UBYTE sapi; T_TIME sysClock; UBYTE disc_request; UBYTE state; UBYTE data [IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE]; } T_TRACE_DATA; #ifdef OPTION_MULTITHREAD #define print_buffer _ENTITY_PREFIXED(print_buffer) #define trace_buffer _ENTITY_PREFIXED(trace_buffer) #endif /* OPTION_MULTITHREAD */ LOCAL char print_buffer[25+IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE]; LOCAL T_TRACE_DATA trace_buffer; /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_fast_trace (UBYTE trace_type, UBYTE channel, UBYTE ch_type, T_TIME trace_time, ULONG trace_mask, UBYTE* data) { T_TRACE_DATA* trace_data; UBYTE o; /* While TC_USER2 is set, measurements and empty frames will be traced always */ if (data AND ((trace_mask & TC_USER2) EQ 0)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[2] EQ 0x01) AND (data[3] EQ 0x03) AND (data[4] EQ 0x49)) return; if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[3] EQ 0x03) AND (data[4] EQ 0x01)) return; else if ( (data[1] EQ 0x03) AND (data[2] EQ 0x01)) return; } } trace_data = &trace_buffer; trace_data->sysClock = trace_time; if (!((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT))) { GET_INSTANCE_DATA; switch (channel) { case C_SACCH0: case C_DCCH0: trace_data->disc_request = dl_data->dcch0_disc_request; trace_data->state = dl_data->state [C_DCCH0]; trace_data->sapi = PS_SAPI_0; break; case C_DCCH3: trace_data->disc_request = dl_data->dcch3_disc_request; trace_data->state = dl_data->state [C_DCCH3]; trace_data->sapi = PS_SAPI_3; break; default: trace_data->disc_request = 0; trace_data->state = 0; trace_data->sapi = NOT_PRESENT_8BIT; break; } } if (data) { if ((trace_type EQ TRACE_UPLINK) OR (trace_type EQ TRACE_DOWNLINK)) { memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE); } else { strncpy ((char *)trace_data->data, (char *)data, IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1); trace_data->data[IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1] = 0; } } else { trace_data->data[0] = 0; } if (ch_type > ELEMENTS(CH_TYPE)) ch_type = 0; if (trace_data->sapi >= ELEMENTS (SAPI_TYPE)) trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1; switch (trace_type) { case TRACE_UPLINK: case TRACE_DOWNLINK: sprintf (print_buffer, "DLTRC:%07lu %c%d %s %s%c ", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, TRACE_TYPE[trace_type], CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi]); o = strlen (print_buffer); array2hex (trace_data->data, print_buffer+o, 23); break; case TRACE_DL_EVENT: sprintf (print_buffer, "DLTRC:%07lu %c%d Ev %s%c %s", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi], trace_data->data); break; case TRACE_PL_EVENT: case TRACE_RR_EVENT: sprintf (print_buffer, "DLTRC:%07lu %d Ev %s %s", trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_type], trace_data->data); break; case TRACE_CHSTATE: sprintf (print_buffer, "DLTRC:%07lu %c%d ST %s%c state=%s", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi], STATES[trace_data->state]); break; default: print_buffer[0] = 0; break; } TRACE_USER_CLASS (TC_USER1, print_buffer); #if 0 if (print_buffer[0]) { #if defined(_SIMULATION_) TRACE_EVENT_WIN (print_buffer); #else /* _SIMULATION_ */ SYST_TRACE_P ((DLTRC,print_buffer)); #endif /* _SIMULATION_ */ } #endif /* 0 */ } #endif /* DL_IMMEDIATE_TRACE */ LOCAL void array2hex (UBYTE *inarray, char *outarray, int size) { int col=0, n=0; UBYTE b, nh, nl; while (n < size) { b = inarray[n++]; nh = b>>4; nl = b&0x0f; outarray[col++] = nh > 9 ? nh + 'A' - 10 : nh + '0'; outarray[col++] = nl > 9 ? nl + 'A' - 10 : nl + '0'; } outarray[col] = 0; } #endif /* DL_TRACE_ENABLED */ #if defined (DL_TRACE_PFREE) GLOBAL void* my_pfree(void *pointer, int line, char *file) { char buffer[23]; sprintf (buffer, "%s#%u:%p", file+2, line, pointer); dl_trace (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, buffer); if (pointer) { PFREE (pointer); } else { SYST_TRACE_P((SYST, "%s#%u: PFREE(NULL)", file, line)); } return NULL; } #endif /* DL_TRACE_PFREE */ #endif /* DL_TRACE_C */