diff src/cs/drivers/drv_app/lcc/lcc_task.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/drivers/drv_app/lcc/lcc_task.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,442 @@
+/******************************************************************************
+ * Power Task (pwr)
+ * Design and coding by Svend Kristian Lindholm, skl@ti.com
+ *
+ * Main PWR Task
+ *
+ * $Id: pwr_task.c 1.1 Wed, 20 Aug 2003 10:22:37 +0200 skl $
+ *
+ ******************************************************************************/
+
+#include "lcc/lcc.h"
+#include "lcc/lcc_task.h"
+#include "lcc/lcc_handle_message.h"
+#include "lcc/lcc_tm_i.h"
+#include "lcc/lcc_trace.h"
+
+#include "rv/rv_defined_swe.h"
+
+#include "ffs/ffs.h"
+
+#include <string.h>
+/******************************************************************************
+ * Globals and function prototypes
+ ******************************************************************************/
+
+extern T_PWR_CTRL_BLOCK *pwr_ctrl;
+extern T_PWR_CFG_BLOCK *pwr_cfg;
+
+// Event handling functions
+T_RV_RET process_spi_adc_indication             (T_PWR_REQ *request);
+
+// Timer event handling functions
+T_RV_RET process_pwr_handle_T1_expiration       (T_PWR_REQ *request);
+T_RV_RET process_pwr_handle_T2_expiration       (T_PWR_REQ *request);
+T_RV_RET process_pwr_handle_T3_expiration       (T_PWR_REQ *request);
+T_RV_RET process_pwr_handle_T4_expiration       (T_PWR_REQ *request);
+T_RV_RET process_pwr_handle_mod_cycle_expiration(T_PWR_REQ *request);
+T_RV_RET process_pwr_handle_mmi_info_expiration (T_PWR_REQ *request);
+
+// Interrupt event handling functions
+T_RV_RET process_abb_chg_unplugged_ind          (T_PWR_REQ *request);
+
+
+T_RVM_RETURN pwr_check_files(void);
+T_RVM_RETURN pwr_read_files(void);
+T_RVM_RETURN pwr_read_chg_files(void);
+T_RVM_RETURN pwr_read_cal_files(void);
+
+void build_name(const char *ch_pre, char *cfg_id , UINT8 index, const char * ch_post,  char * name);
+
+// FFS function prototypes
+effs_t ffs_stat(const char *name, struct stat_s *stat);
+int ffs_fread(const char *name, void *addr, int size);
+
+void ttr(unsigned trmask, char *format, ...);
+void str(unsigned mask, char *string);
+
+
+/******************************************************************************
+ * PWR Task
+ ******************************************************************************/
+
+// This function checks the existance of FFS directories and files related
+// to the PWR module - See RD818
+// If the existance of the object is MANDATORY pwr_check_files returns an 
+// error and the PWR configuration is stopped
+// If the existance of the object is OPTIONAL pwr_check_files a
+// warning is given and the PWR configuration proceeds
+
+T_RVM_RETURN pwr_check_files()
+{
+    T_FFS_SIZE error;
+    T_FFS_STAT stat;
+
+    ttw(ttr(TTrInit, "pwr_check_files(%d)" NL, 0));
+
+    // Check directories:
+    // /pwr                       MANDATORY
+    // /pwr/bat                   MANDATORY
+    // /pwr/chg                   OPTIONAL
+    // /mmi                       OPTIONAL
+    // /mmi/pwr                   OPTIONAL
+
+    // MANDATORY directories
+    if ((error = ffs_stat("/pwr", &stat)) == EFFS_OK) {
+        if (stat.type != OT_DIR) {
+           ttr(TTrFatal, "pwr exists but is not a directory %d" NL, 0);
+           return EFFS_NOTADIR;
+        }
+    } else {
+        ttr(TTrFatal, "no /pwr directory %d" NL, 0);
+        return error;
+    }
+    if ((error = ffs_stat("/pwr/bat", &stat)) == EFFS_OK) {
+        if (stat.type != OT_DIR) {
+           ttr(TTrFatal, "/pwr/bat exists but is not a directory %d" NL, 0);
+           return EFFS_NOTADIR;
+        }
+    } else {
+        ttr(TTrFatal, "no /pwr/bat directory %d" NL, 0);
+        return error;
+    }
+
+
+    // OPTIONAL directories
+    if ((error = ffs_stat("/pwr/chg", &stat)) == EFFS_OK) {
+        if (stat.type != OT_DIR) {
+           ttr(TTrWarning, "/pwr/chg exists but is not a directory %d" NL, 0);
+        }
+    } else {
+        ttr(TTrWarning, "no /pwr/chg directory %d" NL, 0);
+    }
+    if ((error = ffs_stat("/mmi", &stat)) == EFFS_OK) {
+        if (stat.type != OT_DIR) {
+           ttr(TTrWarning, "/mmi exists but is not a directory %d" NL, 0);
+        }
+    } else {
+        ttr(TTrWarning, "no /mmi directory %d" NL, 0);
+    }
+    if ((error = ffs_stat("/mmi/pwr", &stat)) == EFFS_OK) {
+        if (stat.type != OT_DIR) {
+           ttr(TTrWarning, "/mmi/pwr exists but is not a directory %d" NL, 0);
+        }
+    } else {
+        ttr(TTrWarning, "no /mmi/pwr directory %d" NL, 0);
+    }
+
+    // Check calibration files:
+    // /pwr/vbat.cal              MANDATORY
+    // NOT checked - it MUST be present - else we will have no Vbat measurements
+
+    // Check configuration files:
+    // /pwr/common.cfg            MANDATORY
+    // /pwr/bat/bat<N>.cfg        MANDATORY
+    // /pwr/bat/temp<N>.cfg       OPTIONAL
+    // /pwr/chg/chg<N>.cfg        OPTIONAL
+
+
+    // MANDATORY files
+    if ((error = ffs_stat("/pwr/common.cfg", &stat)) == EFFS_OK) {
+        if (stat.type != OT_FILE) {
+           ttr(TTrFatal, "/pwr/common.cfg exists but is not a file %d" NL, 0);
+           return EFFS_NOTADIR;
+        }
+    } else {
+        ttr(TTrFatal, "no /pwr/common.cfg file %d" NL, 0);
+        return error;
+    }
+
+    ttw(ttr(TTrInit, "pwr_check_files(%d)" NL, 0xFF));
+    return RV_OK;
+}
+
+// This function reads the FFS pwr configuration files
+//                               /pwr/vbat.cal          MANDATORY
+//                               /mmi/pwr/bsie          OPTIONAL
+//                               /pwr/common.cfg        MANDATORY
+//                               /pwr/bat/bat<n>.cfg    MANDATORY
+//                               /pwr/bat/temp<n>.cfg   MANDATORY
+//
+// Precondition: Files have been checked with pwr_check_files()
+//               Therefore we know they exist. Charger files are read later.
+//
+
+T_RVM_RETURN pwr_read_files()
+{
+    T_FFS_SIZE error;
+    T_FFS_STAT stat;
+    char name[20];
+    uint8 i;
+    char cfg_id;
+
+    ttw(ttr(TTrInit, "pwr_read_files(%d)" NL, 0));
+
+
+    // Brute force of charger configuration ? /pwr/chg/force
+    if ((error = ffs_stat("/pwr/chg/force", &stat)) == EFFS_OK) {
+        error = ffs_fread("/pwr/chg/force", &pwr_cfg->data.cforce, 1);
+        ttw(ttr(TTrInitLow, "Read /pwr/chg/force(%d)" NL, error));
+        pwr_cfg->data.chg_cfg_id = pwr_cfg->data.cforce + '0';
+        pwr_ctrl->chg_cfg_id     = pwr_cfg->data.cforce;
+    } else {
+        // Use 'normal' 'plug & play' configuration
+        pwr_cfg->data.cforce = 0;
+        pwr_cfg->data.chg_cfg_id = 1 + '0'; // Default
+        pwr_ctrl->chg_cfg_id     = 1;       // Default
+    }
+
+    // Brute force of battery configuration ? /pwr/bat/force
+    if ((error = ffs_stat("/pwr/bat/force", &stat)) == EFFS_OK) {
+        error = ffs_fread("/pwr/bat/force", &pwr_cfg->data.bforce, 1);
+        ttw(ttr(TTrInitLow, "Read /pwr/bat/force(%d)" NL, error));
+        pwr_ctrl->cfg_id     = pwr_cfg->data.bforce;
+        pwr_cfg->data.cfg_id = pwr_cfg->data.bforce + '0';
+    } else {
+        // Use 'normal' 'plug & play' configuration
+        // Precondition: We have a reliable battery id measurement
+        pwr_cfg->data.bforce = 0;
+        ttw(ttr(TTrInitLow, "Plug & play bat_id=%d" NL, pwr_cfg->data.bat_id));
+    }
+
+    // Read /pwr/common.cfg
+    error = ffs_fread("/pwr/common.cfg", &pwr_cfg->common, PWR_COMMON_CFG_SIZE);
+    ttw(ttr(TTrInitLow, "Read /pwr/common.cfg(%d)" NL, error));
+
+    // Read /mmi/pwr/bsie 
+    // Apply defaults if file doesn't exist
+    if ((error = ffs_stat("/mmi/pwr/bsie.cfg", &stat)) == EFFS_OK) {
+        if (stat.type != OT_FILE) {
+           ttr(TTrWarning, "/mmi/pwr/bsie.cfg exists but is not a file %d" NL, 0);
+           return EFFS_NOTAFILE;
+        } else {
+           error = ffs_fread("/mmi/pwr/bsie.cfg", &pwr_cfg->mmi, sizeof(pwr_cfg->mmi));
+           ttw(ttr(TTrInitLow, "Read /mmi/pwr/bsie.cfg(%d)" NL, error));
+        }
+    } else {
+        ttr(TTrWarning, "no /mmi/pwr/bsie file %d" NL, 0);
+        // Apply defaults
+        pwr_cfg->mmi.repetition = PWR_MMI_REP_THR;
+    }
+
+    if (pwr_cfg->data.bforce > 0) {
+        // Brute force battery configuration
+        build_name("/pwr/bat/bat", &pwr_cfg->data.cfg_id, 12, ".cfg", name);
+        error = ffs_fread(name, &pwr_cfg->bat, PWR_BAT_CFG_SIZE);
+        build_name("/pwr/bat/temp", &pwr_cfg->data.cfg_id, 13, ".cfg", name);
+        error = ffs_fread(name, &pwr_cfg->temp, PWR_TEMP_CFG_SIZE);
+    } else {
+        // Find out which <n> and read /pwr/bat/bat<n>.cfg
+        // We know that at least one battery configuration file exists
+        // Pick the file that matches the bat_id measured earlier
+
+        for (i = 1; i <= 5; i++) {
+            cfg_id = i + '0';
+            build_name("/pwr/bat/bat", &cfg_id, 12, ".cfg", name);
+            error = ffs_fread(name, &pwr_cfg->bat, PWR_BAT_CFG_SIZE);
+            // Found the right battery id??
+            if ((pwr_cfg->data.bat_id >= pwr_cfg->bat.id_low) &&
+                (pwr_cfg->data.bat_id <= pwr_cfg->bat.id_high)) {
+                ttw(ttr(TTrInitLow, "Chose %s" NL, name));
+                // Save the configuration number in the name
+                pwr_ctrl->cfg_id = i;
+                pwr_cfg->data.cfg_id = cfg_id;
+                pwr_ctrl->flag_bat_unknown = 0;
+
+                // Read the corresponding temperature configuration
+                build_name("/pwr/bat/temp", &pwr_cfg->data.cfg_id, 13, ".cfg", name);
+                error = ffs_fread(name, &pwr_cfg->temp, PWR_TEMP_CFG_SIZE);
+                break;
+            }
+        }
+
+        // Check if a matching battery configuration was found
+        if ((pwr_cfg->data.cfg_id < '1') || (pwr_cfg->data.cfg_id > '5')) {
+            pwr_cfg->data.cfg_id = '1';
+            pwr_ctrl->cfg_id = 1;
+            ttr(TTrWarning, "No matching battery configuration id - Defaults to %d" NL, pwr_ctrl->cfg_id);
+
+            // Flag that battery configuration was unknown
+            // Inform the MMI later when it has registered
+            pwr_ctrl->flag_bat_unknown = 1;
+        }
+    }
+
+    ttw(ttr(TTrInit, "pwr_read_files(%d)" NL, 0xFF));
+    return RV_OK;
+}
+
+
+// Read calibration files only
+T_RVM_RETURN pwr_read_cal_files()
+{
+    T_FFS_SIZE error;
+
+    // Read /pwr/vbat.cal
+    error = ffs_fread("/pwr/vbat.cal", &pwr_cfg->cal.vbat, sizeof(pwr_cfg->cal.vbat));
+    if ( error < EFFS_OK )
+       return RVM_INTERNAL_ERR;
+    ttw(ttr(TTrInitLow, "Read /pwr/vbat.cal(%d)" NL, error));
+    ttw(ttr(TTrInitLow, "pwr_cfg->cal.vbat.alfa_num=%d" NL, pwr_cfg->cal.vbat.alfa_num));
+    ttw(ttr(TTrInitLow, "pwr_cfg->cal.vbat.alfa_denom=%d" NL, pwr_cfg->cal.vbat.alfa_denom));
+    ttw(ttr(TTrInitLow, "pwr_cfg->cal.vbat.beta=%d" NL, pwr_cfg->cal.vbat.beta));
+    return RVM_OK;
+
+}
+
+// This function reads the FFS pwr configuration file
+// It is invoked when a charger is plugged
+//                               /pwr/chg/chg<n>.cfg    MANDATORY
+T_RVM_RETURN pwr_read_chg_files()
+{
+    T_FFS_SIZE error;
+    char name[20];
+    uint8 i;
+    char chg_id;
+
+    ttw(ttr(TTrInit, "pwr_read_chg_files(%d)" NL, 0));
+
+    if (pwr_cfg->data.cforce > 0) {
+        // Brute force charger configuration
+        build_name("/pwr/chg/chg", &pwr_cfg->data.chg_cfg_id, 12, ".cfg", name);
+        error = ffs_fread(name, &pwr_cfg->chg, PWR_CHG_CFG_SIZE);
+        ttw(ttr(TTrInitLow,"error = %d" NL, error));
+
+        // Readout /pwr/chg/chg<N>.cfg
+        ttw(ttr(TTrInitLow,"chg.cfg: type: %d" NL, pwr_cfg->chg.type));
+        ttw(ttr(TTrInitLow,"ichg_max: %d" NL, pwr_cfg->chg.ichg_max));
+        ttw(ttr(TTrInitLow,"vchg_low: %d" NL, pwr_cfg->chg.vchg_low));
+        ttw(ttr(TTrInitLow,"vchg_high: %d" NL, pwr_cfg->chg.vchg_high));
+    } else {
+        // Find out which <n> and read /pwr/chg/chg<n>.cfg
+        // We know that at least one charger configuration file exists
+        // Pick the file that matches the chg_id measured earlier
+
+        for (i = 1; i <= 5; i++) {
+            chg_id = i + '0';
+            build_name("/pwr/chg/chg", &chg_id, 12, ".cfg", name);
+            error = ffs_fread(name, &pwr_cfg->chg, PWR_CHG_CFG_SIZE);
+            ttw(ttr(TTrInitLow,"error = %d" NL, error));
+
+            // Readout /pwr/chg/chg<N>.cfg
+            ttw(ttr(TTrInitLow,"chg.cfg: type: %d" NL, pwr_cfg->chg.type));
+            ttw(ttr(TTrInitLow,"ichg_max: %d" NL, pwr_cfg->chg.ichg_max));
+            ttw(ttr(TTrInitLow,"vchg_low: %d" NL, pwr_cfg->chg.vchg_low));
+            ttw(ttr(TTrInitLow,"vchg_high: %d" NL, pwr_cfg->chg.vchg_high));
+
+            // Found the right charger id??
+            if ((pwr_cfg->data.chg_id > pwr_cfg->chg.vchg_low) &&
+                (pwr_cfg->data.chg_id < pwr_cfg->chg.vchg_high)) {
+                ttw(ttr(TTrInitLow, "Chose %s" NL, name));
+                // Save the configuration number in the name
+                pwr_ctrl->chg_cfg_id = i;
+                pwr_cfg->data.chg_cfg_id = chg_id;
+                pwr_ctrl->flag_chg_unknown = 0;
+
+                break;
+            }
+        }
+
+        // Check if a matching charger configuration was found
+        if ((pwr_cfg->data.chg_cfg_id < '1') || (pwr_cfg->data.chg_cfg_id > '5')) {
+            pwr_cfg->data.chg_cfg_id = '1';
+            pwr_ctrl->chg_cfg_id = 1;
+            ttr(TTrWarning, "No matching charger configuration id - Defaults to %d" NL, pwr_ctrl->chg_cfg_id);
+
+            // Flag that charger configuration was unknown
+            // Inform the MMI later when it has registered
+            pwr_ctrl->flag_chg_unknown = 1;
+        }
+    }
+    ttw(ttr(TTrInit, "pwr_read_chg_files(%d)" NL, 0xFF));
+}
+
+void *pwr_malloc(int size)
+{
+    void *addr;
+
+    if (rvf_get_buf(pwr_ctrl->prim_id, size, &addr) == RVF_RED) {
+        ttr(TTrFatal, "PWR FATAL: No Memory (%d)" NL, pwr_ctrl->state);
+        return NULL;
+    }
+
+    return addr;
+}
+
+void pwr_free(void *addr)
+{
+    int error;
+
+    ttw(ttr(TTrEvent, "pwr_free (%d)" NL, 0));
+    if ((error = rvf_free_buf(addr)) != RV_OK) {
+        ttr(TTrFatal, "PWR FATAL: pwr_free (%d)" NL, error);
+    }
+}
+
+
+void pwr_task()
+{
+    void                 *request;
+    struct pwr_req_s     *pwr_request;
+    int    error;
+
+    ttw(ttr(TTrEnv, "pwr_task(%d)" NL, 0));
+
+    while (1) {
+        rvf_wait(RVF_TASK_MBOX_0_EVT_MASK,0);
+        request  = rvf_read_mbox(RVF_TASK_MBOX_0);
+        pwr_request = (struct pwr_req_s *)request;
+
+        if (request != NULL) {
+
+            ttw(ttr(TTrEvent,    "Received Event(%d)" NL, pwr_request->header.msg_id));
+            ttw(ttr(TTrEventLow, "src_addr_id(%d)" NL, pwr_request->header.src_addr_id));
+            ttw(ttr(TTrEventLow, "dest_addr_id(%d)" NL, pwr_request->header.dest_addr_id));
+
+            switch (pwr_request->header.msg_id) {
+            case PWR_CHARGER_PLUGGED_IND:
+                // Sometimes (low voltage - init) receiving a ghost charger plug although interrupts are disabled
+                pwr_free(request);
+                break;
+            case PWR_CHARGER_UNPLUGGED_IND:
+                error = process_abb_chg_unplugged_ind(pwr_request);
+                break;
+            case PWR_ADC_IND :
+                error = process_spi_adc_indication(request);
+                break;
+
+            // Timers
+
+            case TIMER_T1_EXPIRED:
+                error = process_pwr_handle_T1_expiration(request);
+                break;
+            case TIMER_T2_EXPIRED:
+                error = process_pwr_handle_T2_expiration(request);
+                break;
+            case TIMER_T3_EXPIRED:
+                error = process_pwr_handle_T3_expiration(request);
+                break;
+            case TIMER_T4_EXPIRED:
+                error = process_pwr_handle_T4_expiration(request);
+                break;
+            case TIMER_MOD_CYCLE_EXPIRED:
+                error = process_pwr_handle_mod_cycle_expiration(request);
+                break;
+            case TIMER_MMI_INFO_EXPIRED:
+                error = process_pwr_handle_mmi_info_expiration(request);
+                break;
+            default :
+                {
+                ttr(TTrFatal, "PWR FATAL: Unknown Event: %d" NL, pwr_request->header.msg_id);
+                ttr(TTrFatal, "                   State: %d" NL, pwr_ctrl->state);
+                // Exception Handling - Unknown Event
+                }
+            }
+        } else {
+            // Exception Handling - NULL pointer
+            ttr(TTrFatal, "PWR FATAL: NULL pointer (%d)" NL, pwr_ctrl->state);
+        }
+    }
+    ttw(ttr(TTrEnv, "pwr_task(%d)" NL, 0xFF));
+}
+