FreeCalypso > hg > fc-tourmaline
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)); +} +