view src/cs/drivers/drv_app/lcc/lcc_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

/******************************************************************************
 * 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));
}