view src/cs/services/etm/etm_tmcore.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 12b20090b46a
children
line wrap: on
line source

/********************************************************************************
 * Enhanced TestMode (ETM)
 * @file	tmcore.c
 *
 * @author	Kim T. Peteren (ktp@ti.com)
 * @version 0.1
 *

 *
 * History:
 *
 * 	Date       	Modification
 *  ------------------------------------
 *  16/06/2003	Creation
 *  02/07/2003  Removed l1_config.TestMode check from CODEC Write
 *  17/03/2004  Updated etm_version
 *  30/03/2004  Updated etm_dieID_read() func. regarding get die id for 16 bits
 *              instead of 8 bits.
 *
 * (C) Copyright 2003 by Texas Instruments Incorporated, All Rights Reserved
 *********************************************************************************/

#include "rv/rv_defined_swe.h"
#include "rv/rv_general.h"

#include "etm/etm.h"
#include "etm/etm_api.h"
#include "etm/etm_trace.h"
#include "etm/etm_version.h"

#include "abb/abb.h"

#include "spi/spi_drv.h"
extern void tr_etm_init(unsigned int mask);

/* FreeCalypso addition for KPD_PWR testing */
#include "kpd/kpd_power_api.h"

/* Further FreeCalypso addition: phone-on command */
#ifdef RVM_FCBM_SWE
#include "fcbm/fcbm_send_msg.h"
#endif

// Version of the ETM CORE module
// See the file etm_version.h

/******************************************************************************
 * DIE ID settings
 *****************************************************************************/

#define BE_STREAM_TO_ARRAY(a, p, l) {register INT32 i; for (i = 0; i < l; i++) a[i] = *(UINT8*)(p)++;}

/* DIE ID register */
#if ((CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11))      //For D-Sample: $CHIPSET  =  8 (=10 for D-sample AMR, 11 for GSMLITE).
#define DIE_ID_REG    (MEM_DEV_ID0 | 0xF010) //+ 0xFFFEF010 for Calypso
#else
#if (CHIPSET == 12)                         //For E-Sample: $CHIPSET   =  12.
#define DIE_ID_REG    (0xFFFE0000 | 0xF004)	//+ 0xFFFEF004 for Calypso Plus
#endif
#endif

/* DIE ID SIZE is 4 words (16 bits)long */
#define DIE_ID_SIZE        4

//Copied from rv_general.h:
//#define BE_STREAM_TO_ARRAY(a, p, l) {register INT32 i; for (i = 0; i < l; i++) a[i] = *(UINT16*)(p)++;}


/******************************************************************************
 * Internal prototypes
 *****************************************************************************/

T_ETM_PKT *etm_core_setup(uint8 fid);
int etm_core(uint8 *buf, int size);

/******************************************************************************
 * Register the Core Module to the ETM database
 *****************************************************************************/

int etm_core_init(void)
{
    int result;

    result = etm_register("CORE", ETM_CORE, 0, 0, etm_core);
    return result;
}


/******************************************************************************
 * Memory read/write Functions
 *****************************************************************************/

// Describe the payload of the mem protocol !!!!!!
// |--type(1)-|--partnum(1)-|--addr(4)-|--data(?)-|

int etm_mem(T_ETM_PKT *pkt, uint8 *buf)
{
   int num, unitsize, error;
   uint8 type, param;
   uint8  *mem8;
   uint16 *mem16;
   uint32 *mem32;
   uint32 addr, tmp;
   static unsigned char test_buf[64];

   param = unitsize = *buf & 0x3;
   if (unitsize == 0)
       unitsize = 4;

   type = *buf & 0x10;
   buf++;

   num = *buf++;
   addr = etm_get32(buf);
   buf += 4;

   tr_etm(TgTrCore, "ETM CORE: _mem: type(0x%x) addr(0x%x) partnum(%d)", type, addr, num);

   // Put 'parameter' in return packet
   if ((error = etm_pkt_put8(pkt, param)) < 0) {
       return error;
   }

   switch (type) {
   case 0: // READ(0x00)
       switch (unitsize) {
       case 1:
           mem8 = (uint8 *) addr;
           while (num--) {
               if ((error = etm_pkt_put8(pkt, *mem8++)) < 0)
                   break;
           }
           break;
       case 2:
           mem16 = (uint16 *) addr;
           while (num--) {
               if ((error = etm_pkt_put16(pkt, *mem16++)) < 0)
                   break;
           }
           break;
       case 4:
           mem32 = (uint32 *) addr;
           while (num--) {
               if ((error = etm_pkt_put32(pkt, *mem32++)) < 0)
                   break;
           }
           break;
       }
       break;

   case 16: // WRITE(0x10)
       switch (unitsize) {
       case 1:
           mem8 = (uint8 *) addr;
           while (num--) {
               *mem8++ = etm_get8(buf);
               buf += 1;
           }
           break;
       case 2:
           mem16 = (uint16 *) addr;
           while (num--) {
               *mem16++ = tmp = etm_get16(buf);
               buf += 2;
           }
           break;
       case 4:
           mem32 = (uint32 *) addr;
           while (num--) {
               *mem32++ = etm_get32(buf);
               buf += 4;
           }
           break;
       }
       break;
   default:
       return ETM_NOSYS;
   }

   if (error < 0)
       return error;

    return ETM_OK;
}


/******************************************************************************
 * CODEC Functions
 *****************************************************************************/

// ETM sends both page value and register address in one byte.
// Bit field is:  PPPR RRRR
// where P = page bit, R = register address bits and X = don't care bits.

int etm_codec_write(T_ETM_PKT *pkt, uint8 *buf)
{
    extern void ABB_Write_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id, SYS_UWORD16 value);
    uint16  page, reg, data;
    int result, reg_data;

    reg_data = *buf++;
    if ((result = etm_pkt_put8(pkt, reg_data)) < 0)
        return result;

    page = (reg_data  >> 5) & 0x3;
    reg  =  reg_data        & 0x1F;
    data = etm_get16(buf);

    tr_etm(TgTrCore, "ETM CORE: _codec_write: page(%d) reg(%d) data(0x%x)",
           page, reg, (data & 0x3ff));

    if (page > 7 && reg > 32)
        return ETM_INVAL;
    else {
        // The function below expects a 1 for page 0 and a 2 for page 1.
        // The register address value is left-shifted by 1 since LSB is read/write command bit.
        // The value is written in the 10 MSB's of register.
        ABB_Write_Register_on_page(page + 1, reg << 1, (data & 0x3ff));
    }

    return ETM_OK;
}


int etm_codec_read(T_ETM_PKT *pkt, uint8 *buf)
{
    extern SYS_UWORD16 ABB_Read_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id);
    volatile uint16 value;
    uint16 page, reg;
    int result, reg_data;

    reg_data = *buf;
    if ((result = etm_pkt_put8(pkt, reg_data)) < 0)
        return result;

    page = (reg_data  >> 5) & 0x3;
    reg  =  reg_data        & 0x1F;

    if (page > 7 && reg > 32)
        return ETM_INVAL;

    // The function below expects a 1 for page 0 and a 2 for page 1.
    // The register value is left-shifted by 1 since LSB is read/write command bit.
    value = ABB_Read_Register_on_page(page + 1, (reg << 1));

    tr_etm(TgTrCore, "ETM CORE: _codec_read: page(%d) reg(%d) value(0x%x)", page, reg, value);

    result = etm_pkt_put16(pkt, value);
    return result;
}


/******************************************************************************
 * Echo and Reset Functions
 *****************************************************************************/

//structur of data dl: |delay|recvsize|num| = 3x2 bytes
int etm_echo(T_ETM_PKT *pkt, uint8 *data)
{
    int delay, sendsize, i, num, count;

    tr_etm(TgTrCore, "etm_echo:");

    delay = etm_get16(data);
    data += 2;

    sendsize = etm_get16(data);
    if (sendsize > 240)
        return ETM_INVAL;

    data += 2;
    num = etm_get16(data);

    tr_etm(TgTrCore, "ETM CORE: _echo: delay(%d) sendsize(%d) num(%d)",
           delay, sendsize, num);

    if (delay > 0) {
        rvf_delay((delay + 32) * 14 / 64);
    }

    for (i = 0; i < sendsize; i++) {
        pkt->data[i+1] = i;        // data[0] = fid
    }

    pkt->size = sendsize;

    return ETM_OK;
}


int etm_reset(void)
{
// The reset code is taken form Fluid->cmd.c
    int i;

    tr_etm(TgTrCore, "ETM CORE: _reset: Target is Reset");

    // Setup watchdog timer and let it timeout to make a reset
    *(volatile uint16*) 0xfffff804 = 0xFFFF;  // Timer to watchdog
    *(volatile uint16*) 0xfffff800 = 0x0080;  // Start timer
		// Apparently works it only if we read this register?
    i = *(volatile uint16*) 0xfffff802;
    *(volatile uint16*) 0xfffff802 = 0x0001;  // Load timer

    return ETM_OK;
}


/******************************************************************************
 * Set Test Controls
 *****************************************************************************/

int etm_debug(T_ETM_PKT *pkt, uint8 *buf)
{
   int type, error, data;
   char *p;
   extern T_KPD_KEYPAD Kp;

   type = *buf & 0x0F;
   buf++;

   data = etm_get32(buf);

   tr_etm(TgTrCore, "ETM CORE: _debug: type(%d) data(0x%x)", type, data);

   error = 0;
   switch (type) {
   case 0: // (0x00) Allocate Test Buffer
       if ((p = etm_malloc(data)) == NULL)
           error = ETM_NOMEM;
       else
           error = etm_pkt_put32(pkt, (int) p);
       break;
   case 1: // (0x01) Free Test Buffer.
       p = (char *) data;
       etm_free(p);
       break;
   case 2: // (0x02) Set ETM Trace mask
       tr_etm_init(data);
       break;
   case 3: // (0x03) Set read all mem banks stat
       rvf_dump_mem();
       rvf_dump_pool();
       rvf_dump_tasks();
       break;
   /* FreeCalypso addition for KPD_PWR testing */
   case 4:
       (Kp.pressed)(KPD_PWR);
       rvf_delay(5);
       (Kp.released)();
       break;
   case 5:
       (Kp.pressed)(KPD_PWR);
       break;
   case 6:
       (Kp.released)();
       break;
   /* Further FreeCalypso addition: phone-on command */
#ifdef RVM_FCBM_SWE
   case 7:
       fcbm_message_to_task(FCBM_START_PHONE);
       break;
#endif
   default:
       error = ETM_NOSYS;
   }

   if (error < 0)
       return error;

    return ETM_OK;
}

/******************************************************************************
 * Get Version of ...
 *****************************************************************************/
// This is in development ...

int etm_version(T_ETM_PKT *pkt, uint8 *buf)
{
    extern uint16 etm_audio_revision;
    extern uint16 etm_task_revision;
    int error, fid, ffs_tm_version;
    volatile int revision = 0;
    T_VERSION *l1s_version;

    fid = etm_get32(buf);

    tr_etm(TgTrCore, "ETM CORE: _version: fid(0x%x)", fid);

    l1s_version = (T_VERSION*) l1s_get_version();

    switch (fid) {
// Code Versions related to ETM modules
    case SW_REV_ETM_CORE:
        error = etm_pkt_put32(pkt, ETM_CORE_VERSION);
        break;
    case SW_REV_ETM_AUDIO:
        error = etm_pkt_put32(pkt, ETM_AUDIO_VERSION);
        break;
//    case SW_REV_ETM_FFS:
//        ffs_query(Q_FFS_TM_VERSION, &ffs_tm_version);
//        error = etm_pkt_put32(pkt, ffs_tm_version);
        break;
//    case SW_REV_ETM_RF: // Layer1 Testmode Version
//        error = etm_pkt_put32(pkt, TESTMODEVERSION);
//        break;
    case SW_REV_ETM_PWR:
        error = etm_pkt_put32(pkt, ETM_PWR_VERSION);
        break;
    case SW_REV_ETM_BT:
        error = ETM_NOSYS;
        break;
    case SW_REV_ETM_TASK:
        error = etm_pkt_put32(pkt, ETM_VERSION);
        break;
    case SW_REV_ETM_API:
        error = etm_pkt_put32(pkt, ETM_API_VERSION);
        break;
// Code Versions related to L1, see in l1_defty.h
// Get the version on this way "revision = l1s.version.dsp_code_version;"
// doesn't work because of struct aligment -> compile flag -mw !!!!
    case SW_DSP_CODE_VERSION:
        revision = ((T_VERSION*) l1s_version)->dsp_code_version;
        error = etm_pkt_put32(pkt, revision);
        break;
    case SW_DSP_PATCH_VERSION:
        revision = ((T_VERSION*) l1s_version)->dsp_patch_version;
        error = etm_pkt_put32(pkt, revision);
        break;
    case SW_MCU_TCS_PROGRAM_RELEASE:
        revision = ((T_VERSION*) l1s_version)->mcu_tcs_program_release;
        error = etm_pkt_put32(pkt, revision);
        break;
    case SW_MCU_TCS_OFFICIAL: // This version allso identify version of Layer1
        revision = ((T_VERSION*) l1s_version)->mcu_tcs_official;
        error = etm_pkt_put32(pkt, revision);
        break;
    case SW_MCU_TCS_INTERNAL:
        revision = ((T_VERSION*) l1s_version)->mcu_tcs_internal;
        error = etm_pkt_put32(pkt, revision);
        break;
    case SW_MCU_TM_VERSION:
        revision = ((T_VERSION*) l1s_version)->mcu_tm_version;
        error = etm_pkt_put32(pkt, revision);
        break;
    default:
        error = ETM_NOSYS;
    }

    tr_etm(TgTrCore, "ETM CORE: _version: version(%d)", revision);

    if (error < 0)
        return error;

    return ETM_OK;
}


/******************************************************************************
 *  Function for reading the Die-ID from base band processor.
 *****************************************************************************/

int etm_dieID_read(T_ETM_PKT *pkt, uint8 *inbuf)
{
	T_RV_RET result;
	int8 byteCount;
	UINT16 dieID[DIE_ID_SIZE];
	int16 index;
	volatile UINT16 *reg_p = (UINT16 *) DIE_ID_REG;

	tr_etm(TgTrCore, "ETM CORE: _dieID_read: started - Die-ID address(0x%x)", DIE_ID_REG);

	BE_STREAM_TO_ARRAY(dieID, reg_p, DIE_ID_SIZE);

	for (byteCount = 0; byteCount < DIE_ID_SIZE; byteCount++) {

		tr_etm(TgTrCore, "ETM CORE: Die-ID[%i] Byte Read(0x%x)", byteCount, (UINT16)dieID[byteCount]);
        result = etm_pkt_put16(pkt, (UINT8)(((dieID[byteCount]) & 0xFFFF)));
		if (result < 0)
			return result;
	}


	return ETM_OK;
}


/******************************************************************************
 * ETM CORE Main Function - Module
 *****************************************************************************/

int etm_core(uint8 *buf, int size)
{
// Structur of protocol data dl-link: |fid|index|data|

    uint8 mid;
    uint8 fid;
    int error = 0;
    T_ETM_PKT *pkt = NULL;

    fid = *buf++;

    tr_etm(TgTrCore, "ETM CORE: _core: fid(%c):", fid);

    /* Create TestMode return Packet */
    if ((pkt = (T_ETM_PKT *) etm_malloc(sizeof(T_ETM_PKT))) == NULL) {
        return ETM_NOMEM;
    }

    // Init. of return packet
    pkt->mid    = ETM_CORE;
    pkt->status = ETM_OK;
    pkt->size   = 0;
    pkt->index  = 0;
    etm_pkt_put8(pkt, fid);

    switch (fid) {
#ifdef RVM_ATP_SWE
    case 0x60: // old 'G'
        error = etm_at(pkt, (char *) buf);
        break;
#endif
    case 0x61: // old 'M'
        error = etm_mem(pkt, buf);
        break;
    case 0x62: // old 'E'
        error = etm_echo(pkt, buf);
        break;
    case 0x63: // old 'R'
        error = etm_reset();
        break;
    case 0x64: // old 'T'
        error = etm_debug(pkt, buf);
        break;
    case 0x65: // old 'V'
        error = etm_version(pkt, buf);
        break;
    case 0x66: // old 'C'
        error = etm_codec_read(pkt, buf);
        break;
    case 0x67: // old 'D'
        error = etm_codec_write(pkt, buf);
        break;
    case 0x68: // old 'd'
        error = etm_dieID_read(pkt, buf);
        break;
    default:
        tr_etm(TgTrCore,"ETM CORE: _core: fid ERROR");
        error = ETM_NOSYS;
        break;
    }

    if (error < 0) {
        tr_etm(TgTrCore,"ETM CORE: _core: FAILED");
        pkt->status = -error;
    }

    // etm_at(): send func. is controlled by primitive
    if (fid == 'G' && error >= RV_OK) {}
    else
        etm_pkt_send(pkt);

    etm_free(pkt);
    return ETM_OK;
}