view src/cs/services/etm/etm_task.c @ 275:79cfefc1e2b4

audio mode load: gracefully handle mode files of wrong AEC version Unfortunately our change of enabling L1_NEW_AEC (which is necessary in order to bring our Calypso ARM fw into match with the underlying DSP reality) brings along a change in the audio mode file binary format and file size - all those new tunable AEC parameters do need to be stored somewhere, after all. But we already have existing mode files in the old format, and setting AEC config to garbage when loading old audio modes (which is what would happen without the present change) is not an appealing proposition. The solution implemented in the present change is as follows: the audio mode loading code checks the file size, and if it differs from the active version of T_AUDIO_MODE, the T_AUDIO_AEC_CFG structure is cleared - set to the default (disabled AEC) for the compiled type of AEC. We got lucky in that this varying T_AUDIO_AEC_CFG structure sits at the end of T_AUDIO_MODE!
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 30 Jul 2021 02:55:48 +0000
parents 4e78acac3d88
children
line wrap: on
line source

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


 *
 * History:
 *
 * 	Date       	Modification
 *  ------------------------------------
 *  16/06/2003	Creation
 *  03/03/2004  Upadted regarding the ATP + minor ETM DB handling updates
 *  28/07/2004  Fixed ETM database issue
 *
 * (C) Copyright 2003 by Texas Instruments Incorporated, All Rights Reserved
 *********************************************************************************/


#include "etm/etm.h"
#include "etm/etm_api.h"
#include "etm/etm_messages_i.h"
#include "etm/etm_trace.h"
#include "etm/etm_env.h"

#include "audio/audio_api.h"

#include "rv/rv_general.h"
#include "rvf/rvf_api.h"
#include "rvt/rvt_gen.h"
#include "rvf/rvf_target.h" 
#include "rv/rv_defined_swe.h"

#include <string.h>

#ifdef RVM_LCC_SWE
    #include "lcc/lcc_api.h"
    #include "lcc/lcc_cfg_i.h"
    #include "lcc/lcc.h"
    #include "lcc/lcc_env.h"
    #include "lcc/lcc_trace.h"
#endif

// Version of the ETM TASK moved to etm_version.h
//const uint16 etm_task_revision = (1<<12) | (0x1);

/******************************************************************************
 * Globals 
 *****************************************************************************/

#define ETM_DB_MAX     16  // Limited of registered SWEntities into ETM DB
#define ETM_DB_NO_USE  0xFFFFFFFF  //

typedef struct
{	
    char                swe_name[ETM_NAME_MAX_LEN];
    int                 mid;
	int                 task_id;
    T_RVF_ADDR_ID       addr_id;    // Unique mailbox (ID) of the SWE which will
                                    //receive the message
    ETM_CALLBACK_FUNC	rx_callback_func;
} T_ETM_USER_DB;


static T_ETM_USER_DB etm_user_db[ETM_DB_MAX];

static int etm_db_counter = 0;


/******************************************************************************
 * Prototypes 
 *****************************************************************************/

extern T_ETM_ENV_CTRL_BLK *etm_env_ctrl_blk;
#ifdef RVM_LCC_SWE
extern T_PWR_CTRL_BLOCK *pwr_ctrl;
#endif

int etm_database_manager(T_RV_HDR *msg_p);
int etm_forward_packet(int mid, T_RV_HDR *msg);
void etm_error_packet_send(int mid, int error);
void etm_receive(unsigned char *inbuf, unsigned short size);
int etm_ffs_pkt_receive(uint8 *data, int size);

extern int etm_at_atp_message(void *msg);
#ifdef RVM_LCC_SWE
extern int etm_pwr_ul(void *msg);
extern int etm_pwr_dl(T_ETM_PKT *pkt, uint8 *buf, int insize);
#endif

/******************************************************************************
 * Main Testmode Task Loop
 *****************************************************************************/

T_RV_RET etm_task(void)
{  
    extern int etm_core_init(void);
    extern int etm_audio_init(void);
#ifdef RVM_LCC_SWE
    extern int etm_pwr_init(void);
#endif

    T_RV_HDR  *msg = NULL;
    T_ETM_PKT *pkt = NULL; 
    UINT32 start_time = 0;
    UINT32 end_time   = 0;
    UINT16 recv_event, i;  

    int status = RV_OK, buf_size;
    
    /* Entity registration to ETM */
    /* This should be in the individual SWE init. function*/
    status = etm_core_init();
    status = etm_audio_init();
#ifdef RVM_LCC_SWE
    status = etm_pwr_init();
#endif

    while (1)
    {
        recv_event = rvf_wait(0xffff,0); /* Wait (infinite) for all events. */

        start_time = rvf_get_tick_count();
        tr_etm(TgTrEtmLow,"ETM: _task: Time Waiting (%d) tick", start_time - end_time);
        tr_etm(TgTrEtmLow,"ETM: _task: Time Start(%d)", start_time);

        tr_etm(TgTrEtmLow,"ETM: _task: Got message passing to bit filter (0x%x)", recv_event);


        if (!(recv_event & RVF_TASK_MBOX_0_EVT_MASK))
            continue;
        
        /* Read the message in the ETM mailbox */
        if ((msg = rvf_read_mbox(ETM_MAILBOX)) == NULL)
            continue;
        
        tr_etm(TgTrEtmLow,"ETM: _task: msg_id(0x%x)", msg->msg_id);
        
            switch (msg->msg_id) {
                /* Entity registration request or unregistration */
            case ETM_REGISTER_REQ:
            case ETM_UNREGISTER:
                status = etm_database_manager(msg);
                break;
                /* ETM packet received */
            case ETM_DATA_FWR:
                if ((status = etm_forward_packet(((T_ETM_DATA_FWR *) msg)->mid, msg))
                    != ETM_OK)
                    etm_error_packet_send(((T_ETM_DATA_FWR *) msg)->mid, status);
                break;
                /* TM3 packet received */
            case ETM_TM3_DATA_FWR:
                if ((status = etm_forward_packet(ETM_TM3, msg)) != ETM_OK)
                    etm_error_packet_send(ETM_TM3, status);
                break;
            default:
                tr_etm(TgTrEtmLow,"ETM: _task: msg_id '0x%x' NOT supported",
                       msg->msg_id);
            }

        if (status != ETM_OK) {
            tr_etm(TgTrFatal,"ETM: _task: mid(0x%x) ERROR(%d)", 
                   ((T_ETM_DATA_FWR *) msg)->mid, status);
            etm_free(msg); // Free the message
        }
        
        end_time = rvf_get_tick_count();
        tr_etm(TgTrEtmLow,"ETM: _task: Time End (%d)", end_time);
        tr_etm(TgTrEtmLow,"ETM: _task: Time Total (%d) tick", end_time - start_time);
    }
    
    return RV_OK;
}


void etm_error_packet_send(int mid, int error)
{
    T_ETM_PKT *pkt;

    tr_etm(TgTrFatal,"ETM: _error_packet_send: Module(0x%x) ERROR(%d)", mid, error); 

    if (error == ETM_NOMEM) {
        rvf_dump_mem();  
    }
    
    if ((pkt = (T_ETM_PKT *) etm_malloc(sizeof(T_ETM_PKT))) == NULL) {
        rvf_dump_mem();  
        return;
    }
    
    // Init. of return packet
    pkt->mid    = mid;
    pkt->status = -error;
    pkt->size   = 0;
    pkt->index  = 0;

    etm_pkt_send(pkt);
    etm_free(pkt); // Free return packet
}


/* Forwarding of DATA to the SWE can either be done by message/primitive or callback */
int etm_forward_packet(int mid, T_RV_HDR* msg)
{
    ETM_CALLBACK_FUNC rx_callback_func = NULL;
    int i, cid, status = ETM_OK;
    T_ETM_DATA_READY* message_p;
    T_RVF_ADDR_ID swe_addr_id = 0;

    // Search for supported MID in the table
    for (i = 0; etm_user_db[i].mid != TABLE_END; i++)
    {
        tr_etm(TgTrEtmLow,"ETM: _forward_packet: Lookup in db for mid(0x%x)", mid);
    
        if (etm_user_db[i].mid == mid) {
            rx_callback_func = etm_user_db[i].rx_callback_func;
            swe_addr_id = etm_user_db[i].addr_id;
            break;
        }
    }

    tr_etm(TgTrEtmLow,"ETM: _forward_packet: rx_callback_func(%d) swe_addr_id(%d)", 
           *rx_callback_func, swe_addr_id);

    // Invoke the SWE mailbox
    if (swe_addr_id) {
        /* Allocate the memory for the message to send */
        if ((message_p = (T_ETM_DATA_READY*) etm_malloc(sizeof(T_ETM_DATA_READY))) == NULL)
            return ETM_NOMEM; 

        /* Fill the header of the message */
        message_p->header.msg_id = ETM_DATA_READY;
        
        /* Fill the address source id */
        message_p->header.src_addr_id   = rvf_get_taskid(); 
        message_p->header.dest_addr_id  = etm_env_ctrl_blk->addr_id;
        message_p->header.callback_func = NULL;
        
        /* Fill the data in the message */
        memcpy(((T_ETM_DATA_READY*) message_p)->data, ((T_ETM_DATA_FWR*) msg)->data,
               ((T_ETM_DATA_FWR*) msg)->size);
        
        /* Send the message to the entity */
        if ((status = rvf_send_msg(swe_addr_id, message_p)) != RV_OK) {
            tr_etm(TgTrFatal,"ETM: _forward_packet: Failed to sent message - ERROR(%d)", 
                   status);
            return ETM_RV_FATAL;
        }
        etm_free(msg); // Free the message
    }
    // Invoke the SWE callback function
    else if (rx_callback_func) {
        tr_etm(TgTrEtmLow,"ETM: _forward_packet: to mid(0x%x)", mid);
        status = rx_callback_func (((T_ETM_DATA_FWR*) msg)->data, ((T_ETM_DATA_FWR*) msg)->size);
        rx_callback_func = NULL;
        if (status != ETM_OK)
            return status;        
        etm_free(msg); // Free the message
    }
    else {
        return ETM_NOSYS;
    }
    
    return ETM_OK;
}


/******************************************************************************
 * Get and Free buffer (Internal Functions)
 *****************************************************************************/

void *etm_malloc(int size)
{
    /* Memory bank status (red, yellow, green) */
    T_RVF_MB_STATUS mb_status;
    void *addr;

    mb_status = rvf_get_buf(etm_env_ctrl_blk->prim_id, size, &addr);

    /* The flag returned by rvf_get_buf is red, there is not enough
     * memory to allocate the buffer. */
    if (mb_status == RVF_RED) {
		tr_etm(TgTrFatal, "ETM: _malloc: Error to get memory");
        return NULL;
	}
    /* The flag is yellow, there will soon be not enough memory anymore. */
	else if (mb_status == RVF_YELLOW) {
		tr_etm(TgTrFatal, "ETM: _malloc: Getting short on memory");
	}

    tr_etm(TgTrEtmLow,"ETM: _malloc: size(%d) at addr(0x%x)", size, addr);
    return addr;
}

int etm_free(void *addr)
{
    int status;

    tr_etm(TgTrEtmLow,"ETM: _free: addr(0x%x)", addr);

    if ((status = rvf_free_buf(addr)) != RV_OK) {
        tr_etm(TgTrFatal, "ETM: _free: ERROR(%d)", status);
    }
    
    return ETM_RV_FATAL;
}


/******************************************************************************
 * ETM receive Functions API (Internal Functions)
 ******************************************************************************/

/* The input pointer buf point at a complete TM3 packet. */
int etm_tm3_data_forward(uint8 *buf, int size)
{
    /* Type for a registration event. */
    T_ETM_TM3_DATA_FWR *msg;

    tr_etm(TgTrEtmLow, "ETM: _tm3_data_forward: cid(0x%x) size(%d)", *buf, size);

    /* Allocate the memory for the message to send */
    if ((msg = (T_ETM_TM3_DATA_FWR*) etm_malloc(sizeof(T_ETM_TM3_DATA_FWR))) == NULL)
            return ETM_NOMEM; 

    /* Fill the message id */
    msg->header.msg_id        = ETM_TM3_DATA_FWR;

    /* Fill the address source id */
    msg->header.src_addr_id   = rvf_get_taskid();
    msg->header.dest_addr_id  = etm_env_ctrl_blk->addr_id;
    msg->header.callback_func = NULL;

    /* Fill the message parameters */
    msg->size = size;
    msg->cid  = *buf;
    memcpy(&msg->data, buf, size);

// At this point, all the data have been parsed and copied into
// the ETM primitive.  Now we send the primitive to the ETM task.
    if (rvf_send_msg(etm_env_ctrl_blk->addr_id, msg) != RV_OK) {
        tr_etm(TgTrFatal, "ETM: _tm3_data_forward: FAILED");
        return ETM_RV_FATAL;  // msg is auto freed by rvf_send_msg() if error
    }

    return ETM_OK;
}


/* The input pointer buf point at payload of the TM packet, minus mid and cksum. */
int etm_data_forward(char mid, uint8 *inbuf, int size)
{
    /* Type for a registration event. */
    T_ETM_DATA_FWR *msg;

    tr_etm(TgTrEtmLow, "ETM: _data_forward: mid(0x%x) size(%d)", mid, size);

    /* Allocate the memory for the message to send */
    if ((msg = (T_ETM_DATA_FWR*) etm_malloc(sizeof(T_ETM_DATA_FWR))) == NULL)
            return ETM_NOMEM; 

    /* Fill the message id */
    msg->header.msg_id        = ETM_DATA_FWR;

    /* Fill the address source id */
    msg->header.src_addr_id   = rvf_get_taskid(); 
    msg->header.dest_addr_id  = etm_env_ctrl_blk->addr_id;
    msg->header.callback_func = NULL;

    /* Fill the message parameters */
    msg->size = size;
    msg->mid  = mid;
    memcpy(&msg->data, inbuf, size);

// At this point, all the data have been parsed and copied into
// the ETM primitive.  Now we send the primitive to the ETM task.
    if (rvf_send_msg(etm_env_ctrl_blk->addr_id, msg) != RV_OK) {
        tr_etm(TgTrFatal, "ETM: _data_forward: FAILED");
        return ETM_RV_FATAL;  // msg is auto freed by rvf_send_msg() if error
    }

    return ETM_OK;
}


/* This function is registred in the RVT module as the TestMode receive function */
/* It's called every time a TestMode packet is received on the UART and the */
/* data is forwarded to the ETM Entity via a message/primitiv */
/* The function is a callback func. used by the RVT TASK -> UART RX. */

void etm_receive(uint8 *inbuf, unsigned short size)
{
    int error = ETM_NOSYS, i, index;
    char mid;
    unsigned char cksum;
    T_ETM_PKT *pkt;

    tr_etm(TgTrEtmLow, "ETM: _receive: inbuf size(%d)", size);

    // Copy data payload size (size minus MID/CID byte and checksum byte)
    mid = *inbuf++;

    cksum = mid;
    for (i = 0; i < size - 1; i++) {
        cksum ^= inbuf[i];
    }
    
    if (cksum != 0) {
        error = ETM_PACKET;
        goto ETM_RECEIVE_END;
    }
    
    // Check it's a TM3 packet
    if ((0x20 <= mid && mid < 0x27) ||
        (0x30 <= mid && mid < 0x3A) ||
        (0x40 <= mid && mid < 0x49) ||
        (0x50 <= mid && mid < 0x57)) {
        // Forward complete TM3 packet
        error = etm_tm3_data_forward(--inbuf, size);
    }
    else {
        /* Controlling of receptor for regisration */
        for (index=0; index < etm_db_counter; index++)
        {
            if (etm_user_db[index].mid == mid) {
                // Forward ETM packet without <mid> and <cksum>, -2 in size
                error = etm_data_forward(mid, inbuf, size - 2);
                break;
            }
            else if ((index == etm_db_counter) && (etm_user_db[index].mid != mid)) {
                tr_etm(TgTrFatal, "ETM: _receive: mid(0x%x) not supported", mid);
            }
        }
    }

ETM_RECEIVE_END:
    /* Fill in Error status in ETM packet and send */
    if (error) {
        if (error == ETM_NOMEM) {
            rvf_dump_mem();
            return;
        }

        if ((pkt = (T_ETM_PKT *) etm_malloc(sizeof(T_ETM_PKT))) == NULL)
            return; 
        pkt->size   = 0;
        pkt->mid    = mid;
        pkt->status = -error;
        
        etm_pkt_send(pkt);
        etm_free(pkt); // Free return Packet
    }
}


/******************************************************************************
 * Registration manager Functions API (Internal function)
 ******************************************************************************/

int etm_database_add(T_ETM_REGISTER_REQ *msg_p, int index)
{

    memcpy(etm_user_db[index].swe_name, msg_p->name, strlen(msg_p->name));
    etm_user_db[index].mid              =  msg_p->mid;
    etm_user_db[index].task_id          =  msg_p->task_id;
    etm_user_db[index].addr_id          =  msg_p->addr_id;
    etm_user_db[index].rx_callback_func =  msg_p->rx_callback_func;

    etm_user_db[index+1].mid            =  TABLE_END;

    return ETM_OK;
}


int etm_database_manager(T_RV_HDR *msg_p)
{
    int index, mid, status;

    if (msg_p->msg_id == ETM_REGISTER_REQ) {
        mid = ((T_ETM_REGISTER_REQ *) msg_p)->mid;
        
        tr_etm(TgTrEtmLow,"ETM: _database_manager: _REGISTER_REQ reguest is received from (%s)", 
               ((T_ETM_REGISTER_REQ *) msg_p)->name); 
        
        /* Lookup in the ETM DB array */
        for (index=0; index < ETM_DB_MAX; index++)
        {
            /* Use unregistrered space */
            if ((etm_user_db[index].mid == ETM_DB_NO_USE) && (etm_user_db[index].addr_id == 0) && 
                (etm_user_db[index].rx_callback_func == NULL)) {
                status = etm_database_add((T_ETM_REGISTER_REQ*) msg_p, index);
                etm_db_counter++;
                etm_free(msg_p); // Free Message
                return ETM_OK;
            }
            /* Reject double registration */
            else if ((etm_user_db[index].mid == mid) &&
                     ((etm_user_db[index].addr_id != 0) || (etm_user_db[index].rx_callback_func != NULL))) {
                tr_etm(TgTrFatal,"ETM: _database_manager: The Module(0x%x) is registrered", mid);
                etm_free(msg_p); // Free Message
                return ETM_OK;
            }
        }
                    
        /* Add the entity to the etm database */
        if (etm_db_counter < ETM_DB_MAX) {
            status = etm_database_add((T_ETM_REGISTER_REQ*) msg_p, etm_db_counter);
            etm_db_counter++;
            etm_free(msg_p); // Free Message
            return ETM_OK;
        }
        
        etm_free(msg_p); // Free Message
        return ETM_DB_LIMIT;
    }
    
    
    if (msg_p->msg_id == ETM_UNREGISTER) {
        mid = ((T_ETM_UNREGISTER *) msg_p)->mid;
        tr_etm(TgTrEtmLow,"ETM: _database_manager: _UNREGISTER reguest is received from (%s)",
               ((T_ETM_REGISTER_REQ *) msg_p)->name);
        
        /* Lookup in the array, if the SWE is stocked then clean it*/
        for (index=0; index < ETM_DB_MAX; index++) {
            if (etm_user_db[index].mid == mid) {
                etm_user_db[index].mid              = ETM_DB_NO_USE;
                etm_user_db[index].addr_id          = 0;
                etm_user_db[index].rx_callback_func = NULL;
                etm_db_counter--;
                etm_free(msg_p); // Free Message
                return ETM_OK;
            }			
        }

        etm_free(msg_p); // Free Message
        return ETM_INVAL;
    }
    
    etm_free(msg_p); // Free Message
    return ETM_OK;
}