diff gsm-fw/services/etm/etm_task.c @ 164:d78219c43fbf

gsm-fw/services/etm: initial import from the Leonardo semi-src
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 18 Nov 2013 06:39:44 +0000
parents
children 13af69b6a3dc
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/services/etm/etm_task.c	Mon Nov 18 06:39:44 2013 +0000
@@ -0,0 +1,543 @@
+/********************************************************************************
+ * 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;
+}