Files
banban/ql-bootloader/logo/src/main.c
T

1917 lines
57 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu.h"
#include "qspi.h"
#include "reg.h"
#include "system.h"
//#include "uart.h"
#include "ptable.h"
#include "loadtable.h"
#include "sdio.h"
#include "pmic.h"
#include "ff.h"
#include "version_logo.h"
#include "asr_property.h"
#include "guilin.h"
#include "logo_table.h"
#include "asr_lzma.h"
#include "utilities.h"
#include "bsp.h"
#include "quec_cust_startup_feature.h"
#include "quec_lcd_application.h"
#include "ql_boot_power.h"
#include "ql_gpio.h"
#include "fbf_parse.h"
//unsigned int init_cpsr;
/*
*****************************************************************************************
* some debug macros
*
*Note: the following MACRO default state: "CLOSED".
*2. TEST_OTA_DISPLAY_INFO If define this MACRO, add debug code for OTA_DISPLAY
*
*****************************************************************************************
*/
//#define TEST_OTA_DISPLAY_INFO
/*
*****************************************************************************************
* some function MACRO
*
*Note: the following MACROs default state: "OPEN".
*1. ADD_VIBRATOR_IN_CODE If define this MACRO, add vibrator feedback after onkeycheck during boot up.
*2. SUPPORT_MALLOC If define this MACRO, support malloc mechanism
*****************************************************************************************
*/
#define ADD_VIBRATOR_IN_CODE
//#define SUPPORT_MALLOC
#define LZOP_COMPRESSED_MAGIC (0x4f5a4c89)
#define LZMA_COMPRESSED_MAGIC (0x8000005D)
#define LZMA_COMPRESSED_MAGIC1 (0x0800005D)
#define LZMA_COMPRESSED_MAGIC2 (0x0400005D)
#define LZMA_COMPRESSED_MAGIC3 (0x0200005D)
#define LZMA_COMPRESSED_MAGIC4 (0x4C5A4D41)
#define MODE32_svc 0x13
#define SPSR_T_ARM 0
#define SPSR_E_LITTLE 0
#define SPSR_FIQ_BIT (1 << 0)
#define SPSR_IRQ_BIT (1 << 1)
#define SPSR_ABT_BIT (1 << 2)
#define DISABLE_ALL_EXCEPTIONS (SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT)
#define MODE_RW_SHIFT 0x4
#define MODE_RW_32 0x1
#define MODE32_SHIFT 0
#define MODE32_MASK 0x1f
#define SPSR_T_SHIFT 5
#define SPSR_T_MASK 0x1
#define SPSR_E_SHIFT 9
#define SPSR_E_MASK 0x1
#define SPSR_AIF_SHIFT 6
#define SPSR_AIF_MASK 0x7
#define SPSR_MODE32(mode, isa, endian, aif) \
(MODE_RW_32 << MODE_RW_SHIFT | \
((mode) & MODE32_MASK) << MODE32_SHIFT | \
((isa) & SPSR_T_MASK) << SPSR_T_SHIFT | \
((endian) & SPSR_E_MASK) << SPSR_E_SHIFT | \
((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)
/******************************
MACRO NAME: ADD_VIBRATOR_IN_CODE
Despriction: Add vibrator feedback after onkeycheck during boot up.
Default: no vibrator feedback
Owner: Hengshan Yang
Time: 2019-10-16
******************************/
typedef struct {
#if 1 //yqian
uint32_t pc;
#else
uintptr_t pc;
#endif
uint32_t spsr;
} transfer_parameter;
/* enum for battery operation */
typedef enum{
BatteryLevelIsHigh = 0,
BatteryLevelIsMedium,
LowBatteryLevel_And_ChargerNoDetect,
GetBatteryLevelFail,
Calbration_flag_Not_Set,
Dsp_adc_NotExist
}LogoBattery_t;
/* global variable for malloc mechanism */
#ifdef SUPPORT_MALLOC
#define MALLOC_BUFFER_SIZE (0x00050000)
UINT8 g_MallocBuffer[MALLOC_BUFFER_SIZE];
#endif
/* MACRO for config cache */
// NOTE : cache start addr must br multiple of cache size and cache size must 2,4,8..
#define PSRAM_CONFIG_CACHE_START_ADDR 0x7E000000
#define PSRAM_CONFIG_CACHE_SIZE 0x01000000
static int cpy_dsp_by_cp=0;
volatile unsigned long DspBackupAddress;
volatile unsigned long DspFlashAddress;
volatile unsigned long CpExecAddress;
volatile unsigned long CpCopySize;
volatile unsigned long DspExecAddress;
volatile unsigned long DspLoadSize;
volatile unsigned long CpFlashAddress;
volatile unsigned long Cp_2_FlashAddress;
volatile unsigned long rfCopySize;
volatile unsigned long rfFlashAddress;
volatile unsigned long rfLoadAddress;
volatile unsigned long DspImageSize;
volatile unsigned long DspBackupSize;
volatile unsigned long DspRamSize=0;
#define FLASH_CP_START CpFlashAddress
#define FLASH_DSP_START DspFlashAddress
#define PSRAM_DSP_START DspExecAddress
#define DSP_LOAD_SIZE DspLoadSize
#define DSPBACKUP_SIZE DspBackupSize
//#ifdef ONKEY_CHECK
/* Timer0_0 is configured to free run @1MHz from BootROM. */
#define APBTIMER0_CNT_REG 0xD4014090
#define APBTIMER0_EN_REG 0xD4014000
#define APBTIMER0_CLK_REG (0xD4015000+0x34)
//增大heap大小到320KB,LCD刷屏需要这么大的heap
#define LOGO_HEAP_SIZE (0x00012000)
#define CRANEL_4MRAM_RF_ADDRESS 0x7E065000
#define CRANEL_MULTI_RF_ADDRESS 0x7E045000
#define CRANEL_SINGLE_RF_SIZE 0x00005000//20K
//void transfer_control(transfer_parameter *param) __attribute__ ((noreturn));
extern void transfer_control(transfer_parameter *param);
extern void cp_uart_init(void );
/* global variable for record "enable cache and improve core freq" for LZMA */
volatile BOOL g_LzmaOptimizeFlag = FALSE;
extern unsigned int Image$$IMG_END$$Base;
#define LOGO_IMG_END_ADDR ((unsigned int)&(Image$$IMG_END$$Base))
extern BOOL ifPsramLimit200M(void);
void Timer0_enable(BOOL enable){
if(enable){
*(volatile unsigned long*)0xD4015034 = 0x43;
*(volatile unsigned long*)APBTIMER0_EN_REG = 0x1; //enable timer0_0 (in free run)
}else{
*(volatile unsigned long*)0xD4015034 = 0x40;
*(volatile unsigned long*)APBTIMER0_EN_REG = 0x0; //stop Timer0_0
}
}
void GetKeyPartitionInfoFetch(void)
{
_ptentry *cpEntry, *cp_2_Entry;
cpEntry = ptable_find_entry("cp");
CpFlashAddress = cpEntry->vstart;
if(cpEntry == NULL)
CpFlashAddress = CP_BASE_ADDR;//default address as backup one
}
extern void mpu_value_check(void);
extern void TransferControl(unsigned int);
#ifdef LCD_USE_IN_CODE
FIL handle;
unsigned char data_buf[64];
FIL handle_lcd;
#ifdef WATCHLCDST7789_CODE_USE
UINT16 picture_buf_2[115200/2];
#else
UINT16 picture_buf_2[153600/2];
#endif
//LCD function declaration
extern int mci_Logo_LcdInit(UINT32 background);
extern void POWER_ON_LCD_ShowImage(void);
extern VOID mci_LcdSetBrightness(UINT8 level);
extern void mci_Logo_LcdClose(void);
#endif
unsigned long Timer0IntervalInMilli(unsigned long Before, unsigned long After)
{
unsigned long temp = (After - Before);
return (temp / (1000));
}
void SetTimer0CLK(void)
{
*(volatile unsigned long*)APBTIMER0_CLK_REG = 0x43; //Timer0_0
}
unsigned long GetTimer0CNT(void)
{
return *(volatile unsigned long*)APBTIMER0_CNT_REG;
}
void DelayInMilliSecond(unsigned int ms)
{
unsigned long startTime, endTime;
startTime = GetTimer0CNT();
do
{
endTime = GetTimer0CNT();
}
while(Timer0IntervalInMilli(startTime, endTime) < ms);
}
#define PMUTIMER_WDT_STATUS_REG 0xD4080070
BOOL IfWdtResetTriggered(void)
{
return ((*(volatile unsigned long*)PMUTIMER_WDT_STATUS_REG) & 0x1);
}
//#endif
void printlog(void)
{
CP_LOGI("LOGO END\r\n");
//int delay=0x8888;
//while(delay--);
}
#ifdef TEST_OTA_DISPLAY_INFO
extern void OTA_LCD_DisplayText(char *text, int text_length,int16_t text_height_offset,OTA_LANGUAGE_T ota_language);
extern MCI_ASR_LCD_INFO lcd_info_test;
void test_lcd_display(void)
{
INT32 i;
init_lcd_vars();
/* add test code to test lcd dispaly api */
mci_LcdSetBrightness(3); //Turn on the blacklight later to fix "Blurred Screen"
while(1);
}
#endif
void test_float_data( void )
{
float f_1 = 5.0;
float f_2 = 1.0;
CP_LOGD("f_1:%d\r\n",(int)f_1);
}
void test_fitting_calculate( void )
{
// ADC real vol
const INT32 array[2][2] = { { 497, 3265 },
{ 521, 3519 }
};
INT32 result = 0;
float k = 0.0, b = 0.0;
CP_LOGD("func:%s\r\n",__func__);
k = ( (float)array[1][1] - array[0][1] ) / ( array[1][0] - array[0][0] );
b = (float)array[0][1] - array[0][0] * k ;
result = (INT32)(k * 514 + b);
CP_LOGD("result:%d\r\n",result);
}
extern const LogoHeaderTableStruct logo_vb;
BOOL IsDisplayLogo(const LogoBattery_t BatteryRes)
{
/* check startup reason is WDT reset or not? */
if(IfWdtResetTriggered()){
CP_LOGW("Restart by WDT reset\r\n");
return FALSE;
}
/*check restart reason is "RdProduction" or not*/
if(isSysRestartByRdProduction()){
CP_LOGW("Restart By RdProduction\r\n");
return FALSE;
}
/*check battery level */
if(BatteryRes == LowBatteryLevel_And_ChargerNoDetect){
CP_LOGI("battery level is less than low threshold and charger not detect, not display logo\r\n");
return FALSE;
}
if( BatteryRes == GetBatteryLevelFail){
CP_LOGI("battery level get fail, not display logo\r\n");
while(1);
// return FALSE;
}
if( BatteryRes == Calbration_flag_Not_Set || BatteryRes == Dsp_adc_NotExist ){
return FALSE;
}
/* display logo is valid */
CP_LOGI("display logo!\r\n");
return TRUE;
}
//查询Vbatt的电压
void CheckBatteryLevel(LogoBattery_t *pBatteryRes)
{
BOOL IsChargerDectect;
UINT32 battery_level;
static BOOL PrintFlag = TRUE;
while(1)
{
//get battery voltage
if (PMIC_IS_PM813()||PMIC_IS_PM813S())
{
battery_level = pm813_get_bat_vol();
}
else if(PMIC_IS_PM802())
{
battery_level = pm802_get_battery_voltage();
}
else if( PMIC_IS_PM803() || PMIC_IS_PM803L() || PMIC_IS_PM807() )
{
#if defined(ASR_PLATFORM_CRANEM)
PM803_Battery_Res_t pm803_battery_res;
Timer0_enable( TRUE );
pm803_get_battery_voltage( &pm803_battery_res );
battery_level = pm803_battery_res.BatteryValue;
Timer0_enable( FALSE );
uart_printf("===battery_level:%d===\r\n", battery_level);
CP_LOGI("pm803_battery_res:%d\r\n",pm803_battery_res.pm803_status_res);
if( pm803_battery_res.pm803_status_res == PM803_CalbrationFlagNotSet ){
*pBatteryRes = Calbration_flag_Not_Set;
return;
}
if( pm803_battery_res.pm803_status_res == PM803_BatteryFlagNotReady ||
pm803_battery_res.pm803_status_res == PM803_FitFail ||
pm803_battery_res.pm803_status_res == PM803_Load_Dsp_adc_Fail ){
*pBatteryRes = GetBatteryLevelFail;
return;
}
if( pm803_battery_res.pm803_status_res == PM803_Dsp_adc_Not_Exist ){
*pBatteryRes = Dsp_adc_NotExist;
return;
}
#elif defined(ASR_PLATFORM_CRANEL) || defined(ASR_PLATFORM_CRANELR) || defined(ASR_PLATFORM_CRANELRH)
battery_level = get_cranel_vbat();
#else
#error "Please configure the project"
#endif
}
else
{
CP_LOGI("CheckBatteryLevel: Not PM813(S) or PM802 or PM803.\r\n");
return; //PM803 TBD, no GPADC func
}
if(battery_level > BATTERY_LOW_THRESHOLD){
if(battery_level > BATTERY_HIGH_VALUE){
//case: battery voltage is more than "BATTERY_HIGH_VALUE"
*pBatteryRes = BatteryLevelIsHigh;
}else{
//case: battery voltage is more than "low threshold"
CP_LOGI("battery level: %d, more than low threshold: %d\r\n",battery_level,BATTERY_LOW_THRESHOLD);
*pBatteryRes = BatteryLevelIsMedium;
}
break;
}
//check usb is detected ?
IsChargerDectect = PM812_CHARGER_IS_DETECTED();
if(IsChargerDectect == FALSE){
CP_LOGI("battery level: %d, not more than low threshold: %d\r\n",battery_level,BATTERY_LOW_THRESHOLD);
CP_LOGW("Charger disconnect\r\n");
*pBatteryRes = LowBatteryLevel_And_ChargerNoDetect;
break;
}else{
if(PrintFlag == TRUE){
CP_LOGI("battery level: %d, not more than low threshold: %d\r\n",battery_level,BATTERY_LOW_THRESHOLD);
CP_LOGI("Charger Connect\r\n");
CP_LOGI("In Chargering...\r\n");
PrintFlag = FALSE;
}
}
}
return;
}
//此函数检测电池电压,并判断是否进行开机LCD的logo 显示
void Vibrator_And_LogoFeedback(void)
{
BOOL ret_val;
LogoBattery_t BatteryRes;
UINT32 BrightnessLevel;
/* check battery level */
CP_LOGD("check battery level\r\n");
CheckBatteryLevel(&BatteryRes);
CP_LOGD("BatteryRes:%d\r\n",BatteryRes);
switch(BatteryRes)
{
case BatteryLevelIsHigh:
BrightnessLevel = Normal_BackLight_Brightness_Level;
break;
case BatteryLevelIsMedium:
BrightnessLevel = LowerBattery_BackLight_Brightness_Level;
break;
case LowBatteryLevel_And_ChargerNoDetect:
/* If battery level is not more than low threshold and charger not dectect, return to boot33 */
CP_LOGI("battery level is less than low threshold and charger not detect, return to boot33\r\n");
break;
case GetBatteryLevelFail:
CP_LOGW("get battery level fail\r\n");
break;
case Calbration_flag_Not_Set:
CP_LOGW("PM803 Calbration flag not set\r\n");
break;
case Dsp_adc_NotExist:
CP_LOGW("dsp_adc.bin not exist in ptable\r\n");
break;
default:
CP_LOGE("[Logo] BatteryRes: %d is error\r\n",BatteryRes);
while(1);
}
//检查是否需要显示logo,电池电压低或者是热重启,看门狗重启均不进行logo的显示
ret_val = IsDisplayLogo(BatteryRes);
if(ret_val == FALSE)
{
CP_LOGW("Not display logo\r\n");
return;
}
//enable vibrator feedback.
#ifdef ADD_VIBRATOR_IN_CODE
if( PMIC_IS_PM813() )
{
NingboVibratorEnable();
CP_LOGI("VIBRATOR ENABLE\r\n");
}
#endif
#ifdef QUEC_LCD_USR_FOR_LOGO
CP_LOGD("LCD INIT\r\n");
#ifdef QUEC_LCD_SHOWIMAGE_TEST
POWER_ON_LCD_ShowImage(); // // LOGO侧演示示例
#endif
#endif
//If need,disable vibrator feedback
#ifdef ADD_VIBRATOR_IN_CODE
if( PMIC_IS_PM813() )
{
NingboVibratorDisable();
CP_LOGI("VIBRATOR DISABLE\r\n");
}
#endif
}
static CompressedType_e GetCompressedType(UINT32 magic)
{
CompressedType_e type;
switch(magic)
{
case LZOP_COMPRESSED_MAGIC:
CP_LOGD("lzop cpmpressed image\r\n");
type = LZOP;
break;
case LZMA_COMPRESSED_MAGIC:
case LZMA_COMPRESSED_MAGIC1:
case LZMA_COMPRESSED_MAGIC2:
case LZMA_COMPRESSED_MAGIC3:
case LZMA_COMPRESSED_MAGIC4:
CP_LOGD("lzma cpmpressed image\r\n");
type = LZMA;
break;
default:
CP_LOGW("not a compressed image\r\n");
type = NO_COMPRESSED;
break;
}
return type;
}
#define RFBIN_MAGIC 0x52467266
#define PSRAM_BASE_ADDRESS 0x7E000000
#define DSP_ALLIN_M1_SIZE 0x00070000
#ifdef LTEONLY_SINGLE_SIM
void region_decompress_from_flash_to_psram(void){
char region_compress_mark[8];
unsigned schedule_count = 0;
rw_region_item region_info;
unsigned decompress_result,outLen,inLen;
char * rw_cpz_struct_addr=(char*)get_rw_cpz_struct_addr();
CpExecAddress = get_cp_exec_addr(); //CP Exec Addr
//load region compressed struct
memcpy(region_compress_mark,
rw_cpz_struct_addr,
sizeof(region_compress_mark));
if(!strncmp(region_compress_mark, RW_REGION_MARK_PRE_STRING ,strlen(RW_REGION_MARK_PRE_STRING)-1)){
CP_LOGD("[CP ] Region CPZ struct detected from loadtable\r\n");
while(1){
//read NEXT region cpz info struct
memcpy(&region_info
,(void*)(rw_cpz_struct_addr + (sizeof(rw_region_item)*schedule_count++))
,sizeof(rw_region_item));
if(strncmp(region_info.RW_REGION_MARK, RW_REGION_MARK_PRE_STRING ,strlen(RW_REGION_MARK_PRE_STRING)-1))
{
//expend endpoint of RW decompress working flow for compressed image
CP_LOGD("[CP ] stop decompress as no further %s detected\r\n",RW_REGION_MARK_PRE_STRING);
break;
}else if(region_info.RW_REGION_COMPRESSED_ADDR == RW_REGION_COMPRESSED_ADDR_NONE ){
//expend endpoint of RW decompress working flow for uncompressed image
//
//no RW_REGION_COMPRESSED_ADDR detected,
//image did not compressed with /x/tavor/Arbel/build/external_region_compress.pl script
//the decompress would be done by /hop/BSP/src/Cinit1.c
CP_LOGD("[CP ] skip region decompress as no RW_REGION_COMPRESSED_ADDR detected\r\n");
break;
}
//dump region info
CP_LOGD("[CP ] decompress [%8s] from [%.08x] to [%.08x] len[%08x]\r\n",
region_info.RW_REGION_NAME,
region_info.RW_REGION_COMPRESSED_ADDR,
region_info.RW_REGION_EXEC_ADDR,
region_info.RW_REGION_LENGTH
);
decompress_result=LzmaUncompress((unsigned char *)region_info.RW_REGION_EXEC_ADDR,
(size_t *)&outLen,
(const unsigned char *)region_info.RW_REGION_COMPRESSED_ADDR,
(size_t *)&region_info.RW_REGION_LENGTH);
if(decompress_result != 0){
CP_LOGE("\r\n ** ERROR: RW DECOMPRESS ERROR RESULT=[%d] outLen[%08x] inLen[%08x]",decompress_result,outLen,inLen);
while(1) {};
}
}
}
else
{
CP_LOGW("[CP ] Region CPZ struct not detected from loadtable\r\n");
}
}
int copy_dsp_from_flash_to_psram(void)
{
unsigned long magic;
int ret = -1;
int outLen = -1;
unsigned int inLen=0;
UINT32 checksum = 0;
_ptentry *dspEntry;
CompressedType_e CompressedType;
dspEntry = ptable_find_entry("dsp");
DspFlashAddress = dspEntry->vstart;
DspImageSize = dspEntry->vsize;
inLen = DspImageSize;
DspExecAddress = get_dsp_backup_addr();
DspLoadSize = get_dsp_backup_size();
CP_LOGD("logo LOGO_IMG_END_ADDR[%08x]!\r\n",LOGO_IMG_END_ADDR);
if(!CHIP_IS_CRANELRH)
{
if((LOGO_IMG_END_ADDR - PSRAM_CONFIG_CACHE_START_ADDR)>DspLoadSize)
{
CP_LOGE("LOGO image too larger!!![%08x]:[%08x]\r\n",(LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR),DspLoadSize);
return ret;
}
}
//uart_printf("[DSP] decompress from [0x%.08x] to [0x%0.8x] DspRfMoveSize[%08x]\r\n", FLASH_DSP_START ,PSRAM_DSP_START,DspRfMoveSize);
//uart_printf("[DSP] expected released dsp size [0x%.08x], inLen[0x%.08x]\r\n", DSP_COPY_SIZE,*inLen);
magic = *(volatile unsigned long*)DspFlashAddress;
CompressedType = GetCompressedType(magic);
if(CompressedType==LZMA)
{
CP_LOGD("LZMA compressed DSP image.\r\n");
if(!LzmaUncompress((unsigned char *)DspExecAddress,(size_t *)&outLen, (const unsigned char *)DspFlashAddress, (size_t *)&inLen))
{
checksum=CalcImageChecksum((UINT32 *)DspExecAddress, outLen, 0);
CP_LOGD("[DSP] released dsp size [0x%.08x] inLen[0x%.08x] checksum[%.08x]\r\n", outLen,inLen,checksum);
if(outLen != DspLoadSize){
CP_LOGE("[DSP] WARNING: decompressed length [0x%.08x] unmatch with expected [0x%.08x].\r\n",outLen,DspLoadSize);
if(outLen < DspLoadSize){
ret = 0;
}else{
ret = -1;
}
}else{
ret = 0;
}
}else{
CP_LOGE("\r\n ** ERROR: DSP image decompress failed .\r\n");
}
}
if(ret!=0){
while(1);
}
return ret;
}
UINT32 CalcImageChecksum( UINT32* DownloadArea, UINT32 ImageLength,UINT32 checksum)
{
//uart_printf("CalcImageChecksum DownloadArea[%08x],ImageLength[%08x]\r\n",DownloadArea,ImageLength);
UINT32 ImageChecksum = checksum;
UINT32* ptr32 = DownloadArea;
UINT32* pEnd = ptr32 + (ImageLength / sizeof(UINT32));
UINT32 BytesSummed = 0;
while ( ptr32 < pEnd )
{
// checksum format version 2 algorithm as defined by flasher
ImageChecksum ^= (*ptr32);
ptr32++;
BytesSummed += sizeof(UINT32);
}
return ImageChecksum;
}
/*MULTI PA */
#define QUEC_MULTI_PA_SUPPORT
#ifdef QUEC_MULTI_PA_SUPPORT
#define QUEC_RESERVED 1024 //1K
#define QUEC_RF_NUM_MAX 3
#define QUEC_MULTI_PA1 (0x803055AA)
#define QUEC_MULTI_PA2 (0x0830AABB)
#define QUEC_RFBIN_SIZE_NORMAL 4096
#pragma pack (1)
typedef struct
{
const unsigned int multi_flag1;
const unsigned int multi_flag2;
unsigned char rf_num;
long rf_size[QUEC_RF_NUM_MAX];
unsigned char reserved[QUEC_RESERVED];
}rf_head_struct_s;
#pragma pack ()
rf_head_struct_s rf_head ={0};
typedef enum
{
RF_INDEX_1 =0,
RF_INDEX_2,
}QUEC_RF_INDEX_E;
typedef struct
{
unsigned int gpio_num;
unsigned int gpio_1;
unsigned int gpio_2;
}QUEC_PA_GPIO_PARAM_S;
#define QUEC_EC800M_PA_GPIO1_PIN GPIO_PIN_NO_37
unsigned long PA_gpio1_mfpr= 0x148040 ;
#define QUEC_PA_OC_MAX_LEN 6
QUEC_PA_GPIO_PARAM_S quec_EC800M_PA ={1,QUEC_EC800M_PA_GPIO1_PIN};
QUEC_RF_INDEX_E quec_pa_identify_gpio_init(rf_head_struct_s *prf_head)
{
PIN_LEVEL_E gpio1_level=0;
QUEC_RF_INDEX_E ret = RF_INDEX_1;
if(NULL == prf_head && strlen((prf_head->reserved+prf_head->reserved[0]+1))==QUEC_PA_OC_MAX_LEN)
{
uart_printf("[RF ] rf_head invalid\r\n");
return ret;
}
if((prf_head->reserved[0]==quec_EC800M_PA.gpio_num)&&
(prf_head->reserved[1]==quec_EC800M_PA.gpio_1)&&
(strstr((prf_head->reserved+prf_head->reserved[0]+1),"EC800M")!= NULL))
{
ql_gpio_init(QUEC_EC800M_PA_GPIO1_PIN, PIN_DIRECTION_IN, PIN_PULL_PD, PIN_LEVEL_LOW);
*(volatile unsigned long *)(GPIO_MFPR_ADDR(QUEC_EC800M_PA_GPIO1_PIN)) = PA_gpio1_mfpr;
ql_gpio_get_level(QUEC_EC800M_PA_GPIO1_PIN, &gpio1_level);
uart_printf("[RF ] 800M pin1=%d\r\n",gpio1_level);
if(PIN_LEVEL_HIGH == gpio1_level)
{
return RF_INDEX_2;
}
}
else
{
uart_printf("[RF ] one PA\r\n");
}
return RF_INDEX_1;
}
/*
ret =0 , invalid
ret =1 , find multi pa
*/
unsigned int quec_get_rf_info(unsigned int rfFlashAddress,unsigned int rfCopySize,unsigned int *prfFlashAddress,unsigned int *prfCopySize)
{
unsigned ret =0;
rf_head_struct_s rf_head={0};
if((NULL == prfFlashAddress)||(NULL ==prfCopySize))
{
uart_printf("[RF] addr is null\r\n");
return 0;
}
if(rfCopySize <= QUEC_RFBIN_SIZE_NORMAL)
{
uart_printf("[RF] normal,size=%d\r\n",rfCopySize);
return 0;
}
//find whether multi PA
memcpy((void *)&rf_head,(void *)(rfFlashAddress+rfCopySize-sizeof(rf_head)),sizeof(rf_head));
if((QUEC_MULTI_PA1 != rf_head.multi_flag1)||(QUEC_MULTI_PA2 != rf_head.multi_flag2))
{
uart_printf("[RF],num=%d,pa1=0x%x,pa2=0x%x invalid\r\n",rf_head.rf_num,rf_head.multi_flag1,rf_head.multi_flag2);
return 0;
}
if(rf_head.rf_num > QUEC_RF_NUM_MAX)
{
uart_printf("[RF] nornal,rf_num=%d\r\n",rf_head.rf_num);
return 0;
}
uart_printf("[RF] rf_head=%d,%d\r\n",rf_head.reserved[0],rf_head.reserved[1]);
if(RF_INDEX_2 == quec_pa_identify_gpio_init(&rf_head))
{
*prfFlashAddress = rfFlashAddress + rf_head.rf_size[0];
*prfCopySize = rf_head.rf_size[1];
uart_printf("[RF] num=%d,copy rf2_addr:0x%08x\r\n", rf_head.rf_num,*prfFlashAddress);
}
else
{
*prfFlashAddress = rfFlashAddress;
*prfCopySize = rf_head.rf_size[0];
uart_printf("[RF],num=%d,copy rf_addr:0x%08x\r\n",rf_head.rf_num,*prfFlashAddress);
}
return rf_head.rf_num;
}
#endif
int copy_rf_from_flash_to_psram(void)
{
//COPY rf.bin
unsigned int tmp;
_ptentry *rfEntry;
unsigned long magic;
unsigned long offset;
int outLen = -1;
CompressedType_e CompressedType;
UINT32 checksum = 0;
UINT32 rfbackupAddress = 0;
rfLoadAddress = get_rf_load_addr();
rfEntry = ptable_find_entry("rfbin");
rfFlashAddress = rfEntry->vstart;
rfCopySize = rfEntry->vsize;
rfbackupAddress = get_dsp_backup_end_addr();
#ifdef QUEC_MULTI_PA_SUPPORT
unsigned int rfFlashAddress_calc =0,rfCopySize_calc=0;
if(0 != quec_get_rf_info(rfFlashAddress,rfCopySize,&rfFlashAddress_calc,&rfCopySize_calc))
{
rfFlashAddress = rfFlashAddress_calc ;
rfCopySize = rfCopySize_calc;
}
rfCopySize = rfEntry->size;
#endif
CP_LOGW("[RF ] copy from [0x%0.8x] to [0x%0.8x] size[0x%0.8x],backup[0x%0.8x]\r\n",
rfFlashAddress,
rfLoadAddress,
rfCopySize,
rfbackupAddress);
magic = *(volatile unsigned long*)rfFlashAddress;
CompressedType = GetCompressedType(magic);
if (LZMA == CompressedType)
{
//offset = rfLoadAddress - PSRAM_BASE_ADDRESS;
if(!LzmaUncompress((unsigned char *)rfbackupAddress + 8,(size_t *)&outLen, (const unsigned char *)rfFlashAddress, (size_t *)&rfCopySize))
{
if((DspLoadSize == DSP_ALLIN_M1_SIZE) && (IsChipCraneL()||IsChipCraneLR()))
{
rfLoadAddress = get_rf_load_addr();
if((outLen>CRANEL_SINGLE_RF_SIZE) && CHIP_IS_CRANEL){
rfLoadAddress = CRANEL_MULTI_RF_ADDRESS;
}
memcpy(DspExecAddress+(rfLoadAddress-PSRAM_BASE_ADDRESS),(UINT32 *)(rfbackupAddress + 8),outLen);
}else{
*(volatile unsigned long*)rfbackupAddress = RFBIN_MAGIC;
*(volatile unsigned long*)(rfbackupAddress + 4) = outLen;
//checksum=CalcImageChecksum((UINT32 *)(rfbackupAddress + 8), outLen, 0);
}
CP_LOGD("[RF] released rf size [0x%.08x] inLen[0x%.08x] checksum[0x%.08x]\r\n", outLen,rfCopySize,checksum);
}else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
}
}else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
while(1);
}
return 0;
}
void PrepareToExecuteCp(void)
{
#ifdef DEBUG_LZMA
Timer0_enable(TRUE);
#endif
/* [NOTE] move these init code into logo as pm803 use */
/* printf the Chip ID */
CP_LOGD("chip id: 0x%.08x\r\n",GetLongChipID());
enable_psram_cache();
if(copy_dsp_from_flash_to_psram()){
goto FAIL;
}
if(copy_rf_from_flash_to_psram()){
goto FAIL;
}
region_decompress_from_flash_to_psram();
disable_psram_cache();
//CpCoreFreqChangeTo416();
#ifdef DEBUG_LZMA
Timer0_enable(FALSE);
#endif
CP_LOGD("Decompress cp, dsp, rf data END!\r\n");
return;
FAIL:
CP_LOGE("PrepareToExecuteCp failed!\r\n");
while(1);
}
#else
void DecompressRegion(rw_region_item *p_region_info)
{
UINT32 CompressedMagic;
CompressedType_e CompressedType;
unsigned decompress_result,outLen,inLen;
UINT32 UncompressSrcAddr;
#ifdef DEBUG_LZMA
UINT32 t_start,t_end;
#endif
// dump region info ( debug use )
// Dump_RW_REGION_ITEM( p_region_info );
UncompressSrcAddr = p_region_info->RW_REGION_COMPRESSED_ADDR;
/* get compressed magic */
CompressedMagic = *(UINT32 *)UncompressSrcAddr;
CompressedType = GetCompressedType(CompressedMagic);
if(LZMA == CompressedType){
//Prepare for lzma
//if(g_LzmaOptimizeFlag == FALSE)
// LzmaOptimizeSwitch(TRUE);
#ifdef DEBUG_LZMA
t_start = GetTimer0CNT();
#endif
decompress_result = LzmaUncompress((unsigned char *)p_region_info->RW_REGION_EXEC_ADDR,(size_t *)&outLen,
(const unsigned char *)UncompressSrcAddr, (size_t *)&p_region_info->RW_REGION_LENGTH);
CP_LOGD("[CP_RW] decompress from [0x%.08x] to [0x%.08x] outlen[%08x]\r\n",UncompressSrcAddr,(unsigned char *)p_region_info->RW_REGION_EXEC_ADDR,outLen);
#ifdef DEBUG_LZMA
t_end = GetTimer0CNT();
CP_LOGD("[CP_RW][Decopress][%8s] t_start:%ld, t_end:%ld, delta:%ld\r\n",p_region_info->RW_REGION_NAME,t_start,t_end,t_end - t_start);
#endif
}else{
memcpy((unsigned char*)p_region_info->RW_REGION_EXEC_ADDR,(unsigned char*)p_region_info->RW_REGION_COMPRESSED_ADDR, p_region_info->RW_REGION_LENGTH);
decompress_result = 0;
}
if(decompress_result != 0){
CP_LOGE("\r\n ** ERROR: RW DECOMPRESS ERROR RESULT=[%d]",decompress_result);
while(1);
}
}
void region_decompress_from_flash_to_psram(void)
{
char region_compress_mark[8];
unsigned schedule_count = 0;
rw_region_item region_info;
char * rw_cpz_struct_addr=(char *)get_rw_cpz_struct_addr();
//load compressed region struct
memcpy( region_compress_mark,
rw_cpz_struct_addr,
sizeof(region_compress_mark));
if(!strncmp(region_compress_mark, RW_REGION_MARK_PRE_STRING ,strlen(RW_REGION_MARK_PRE_STRING)-1)){
CP_LOGD("Region CPZ struct detected from LDT\r\n");
while(1){
//read NEXT region cpz info struct
memcpy(&region_info
,(void*)(rw_cpz_struct_addr + (sizeof(rw_region_item)*schedule_count++))
,sizeof(rw_region_item));
if(strncmp(region_info.RW_REGION_MARK, RW_REGION_MARK_PRE_STRING ,strlen(RW_REGION_MARK_PRE_STRING)-1))
{
//expend endpoint of RW decompress working flow for compressed image
CP_LOGD("stop decompress as no further %s detected\r\n",RW_REGION_MARK_PRE_STRING);
break;
}
if(region_info.RW_REGION_COMPRESSED_ADDR == RW_REGION_COMPRESSED_ADDR_NONE ){
//expend endpoint of RW decompress working flow for uncompressed image
//
//no RW_REGION_COMPRESSED_ADDR detected,
//image did not compressed with /x/tavor/Arbel/build/external_region_compress.pl script
//the decompress would be done by /hop/BSP/src/Cinit1.c
CP_LOGD("skip region decompress as no RW_REGION_COMPRESSED_ADDR detected\r\n");
break;
}
if(!strncmp(region_info.RW_REGION_NAME,"NON_OTA",7)){
if(asr_property_get("mini.sys.enable")!=0){
CP_LOGD("[CP ] mini system [%8s] no need decompress\r\n",region_info.RW_REGION_NAME);
continue;
}
}
DecompressRegion(&region_info);
}
}
else
{
CP_LOGE("Region CPZ struct not detected from LDT\r\n");
}
}
int copy_cp_from_flash_to_psram(void)
{
//COPY CP.bin
unsigned int tmp;
CP_LOGD("[CP ] start copy CP bin from [0x%0.8x] to [0x%0.8x] ,size=[0x%0.8x]\r\n",
FLASH_CP_START,
CpExecAddress,
CpCopySize);
memcpy( (void *)CpExecAddress,
(void *)FLASH_CP_START,
CpCopySize);
tmp = memcmp((void*)CpExecAddress,
(void*)FLASH_CP_START,
CpCopySize);
CP_LOGD("[CP ] after memcopy , do memcmp result= %s\r\n",(tmp==0)?"SUCCEED":"FAILED");
return tmp;
}
unsigned int get_ps_ncah_address(void)
{
char region_compress_mark[8];
unsigned schedule_count = 0;
rw_region_item region_info;
char * rw_cpz_struct_addr=(char*)get_rw_cpz_struct_addr();
//load region compressed struct
memcpy(region_compress_mark,
rw_cpz_struct_addr,
sizeof(region_compress_mark));
if(!strncmp(region_compress_mark, RW_REGION_MARK_PRE_STRING ,strlen(RW_REGION_MARK_PRE_STRING)-1)){
while(1){
//read NEXT region cpz info struct
memcpy(&region_info
,(void*)(rw_cpz_struct_addr + (sizeof(rw_region_item)*schedule_count++))
,sizeof(rw_region_item));
//dump region info
//uart_printf("[CP ] decompress [%8s] from [%.08x] to [%.08x]\r\n",
// region_info.RW_REGION_NAME,
// region_info.RW_REGION_COMPRESSED_ADDR,
// region_info.RW_REGION_EXEC_ADDR
// );
if(!strncmp(region_info.RW_REGION_NAME,"PS_NCAH",7)){
return region_info.RW_REGION_EXEC_ADDR;
}
}
}
else
{
uart_printf("[CP ] Region CPZ struct not detected from loadtable\r\n");
}
return 0;
}
typedef struct {
uint32_t address;
uint32_t len;
uint32_t reserved[6];
} dsp_backup_info;
UINT32 CalcImageChecksum( UINT32* DownloadArea, UINT32 ImageLength,UINT32 checksum)
{
//uart_printf("CalcImageChecksum DownloadArea[%08x],ImageLength[%08x]\r\n",DownloadArea,ImageLength);
UINT32 ImageChecksum = checksum;
UINT32* ptr32 = DownloadArea;
UINT32* pEnd = ptr32 + (ImageLength / sizeof(UINT32));
UINT32 BytesSummed = 0;
while ( ptr32 < pEnd )
{
// checksum format version 2 algorithm as defined by flasher
ImageChecksum ^= (*ptr32);
ptr32++;
BytesSummed += sizeof(UINT32);
}
return ImageChecksum;
}
int decompress_dsp_from_flash_to_ddr(void)
{
unsigned long DspLoadAddress=0x7E000000;
UINT32 compressed_magic=0,src=0,srclen=0,dst=0,dstlen=0,loadIndex=0;
CompressedType_e CompressedType;
int i=0,ret = 0;;
unsigned decompress_result;
_ptentry *dspEntry;
dspEntry = ptable_find_entry("dsp");
ASR_SECTION_HEADER *section_head=(ASR_SECTION_HEADER *)dspEntry->vstart;
UINT32 checksum=CalcImageChecksum((UINT32 * )section_head, sizeof(ASR_SECTION_HEADER)-4,0);
DspFlashAddress = dspEntry->vstart;
DspExecAddress = get_dsp_backup_addr();
DspLoadSize = get_dsp_backup_size();
uart_printf("[DSP]Magic[0x%.08x],checksum[0x%.08x][0x%.08x]\r\n",section_head->section_head.magic,section_head->section_head.checksum,checksum);
if(section_head->section_head.magic != LZMA_SECTION_MAGIC
|| section_head->section_head.checksum != checksum){
uart_printf("[DSP]Load DSP error!!![0x%.08x],[0x%.08x][0x%.08x]\r\n",section_head->section_head.magic,section_head->section_head.checksum,checksum);
return NotSupportedError;
}
while(section_head->section_head.Image[i].ImagesLen){
src = dspEntry->vstart + section_head->section_head.Image[i].ImagesOffset;
dst = DspExecAddress + loadIndex;
compressed_magic = *(UINT32 *)src;
CompressedType = GetCompressedType(compressed_magic);
if(LZMA == CompressedType){
uart_printf("[DSP]decompress from [0x%.08x] to [0x%.08x]\r\n",src,dst);
srclen = section_head->section_head.Image[i].ImagesLen;
dstlen = 0;
decompress_result=LzmaUncompress((unsigned char *)dst,(size_t *)&dstlen, (const unsigned char *)src, (size_t *)&srclen);
//decompress_result=LZMA_Decompress((UINT_T *)dst, &dstlen, (UINT_T *)src, srclen);
uart_printf("[DSP]decompress result[[%d]],inLen [0x%.08x],outLen [0x%.08x]\r\n",decompress_result,srclen,dstlen);
if(decompress_result !=0 ){
while(1);
}
loadIndex += dstlen;
}
i++;
}
if(loadIndex != DspLoadSize){
if(loadIndex > DspLoadSize){
DspLoadAddress = get_dsp_load_addr();
memcpy((void *)(DspLoadAddress + DspLoadSize),(void *)(DspExecAddress + DspLoadSize),loadIndex - DspLoadSize);
uart_printf("[DSP] WARNING: decompressed length [0x%.08x] unmatch with expected [0x%.08x].DspLoadAddress[%08x]\r\n",loadIndex,DspLoadSize,DspLoadAddress);
ret = 0;
}else{
uart_printf("\r\n ** ERROR: DspLoadSize[0x%.08x].outLen[0x%.08x]\r\n",DspLoadSize,loadIndex);
ret = -1;
}
}
if(ret != 0){
while(1);
}
return NoError;
}
int copy_dsp_from_flash_to_psram(unsigned int * inLen)
{
unsigned long magic;
//COPY DSP.bin
int ret = -1;
CompressedType_e CompressedType;
int outLen = -1;
dsp_backup_info dspbk={0};
magic = *(volatile unsigned long*)FLASH_DSP_START;
CompressedType = GetCompressedType(magic);
if (LZMA == CompressedType) //"a lzop image"
{
CP_LOGD("LZMA compressed DSP image.\r\n");
if((DspLoadSize < (LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR)) && (CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH)){
CP_LOGD("[LzmaUncompress] src: [0x%.08x], srclen: [0x%.08x],dst: [0x%.08x], dstlen: [0x%.08x]",
FLASH_DSP_START,*inLen, DspBackupAddress ,outLen);
if(!LzmaUncompress((unsigned char *)DspBackupAddress,(size_t *)&outLen, (const unsigned char *)FLASH_DSP_START, (size_t *)inLen))
{
CP_LOGD("[DSP] released dsp outLen [0x%.08x] inLen[0x%.08x] DSPBACKUP_SIZE[%08x]\r\n", outLen,*inLen,DSPBACKUP_SIZE);
if(outLen != DSP_LOAD_SIZE){
CP_LOGD("[DSP] WARNING: decompressed length [0x%.08x] unmatch with expected [0x%.08x].\r\n",outLen,DSP_LOAD_SIZE);
}
ret = 0;
}else{
CP_LOGE("\r\n ** ERROR: DSP image decompress failed .\r\n");
while(1);
}
}else{
CP_LOGD("[LzmaUncompress] src: [0x%.08x], srclen: [0x%.08x],dst: [0x%.08x], dstlen: [0x%.08x]",
FLASH_DSP_START,*inLen,(unsigned char *)PSRAM_DSP_START+DSP_LOAD_SIZE,outLen);
if(!LzmaUncompress((unsigned char *)PSRAM_DSP_START+DSP_LOAD_SIZE,(size_t *)&outLen, (const unsigned char *)FLASH_DSP_START, (size_t *)inLen))
{
CP_LOGD("[DSP] released dsp outLen [0x%.08x] inLen[0x%.08x]\r\n", outLen,*inLen);
if(outLen > DSPBACKUP_SIZE){
memcpy((unsigned char *)PSRAM_DSP_START+DSPBACKUP_SIZE,(unsigned char *)PSRAM_DSP_START+DSP_LOAD_SIZE+DSPBACKUP_SIZE,DSP_LOAD_SIZE-DSPBACKUP_SIZE);
CP_LOGD("[DSP] copy dsp to address[0x%.08x] len[0x%.08x]\r\n", (unsigned char *)PSRAM_DSP_START+DSPBACKUP_SIZE,DSP_LOAD_SIZE-DSPBACKUP_SIZE);
}else if(CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH){
DspRamSize = outLen;//this is 1606S 8M psram and all in dsp image
}
memcpy((unsigned char *)DspBackupAddress,(unsigned char *)PSRAM_DSP_START+DSP_LOAD_SIZE,DSPBACKUP_SIZE);
CP_LOGD("[DSP] backup dsp size[%08x] to address[0x%.08x]\r\n",DSPBACKUP_SIZE, (unsigned char *)DspBackupAddress);
if(outLen != DSP_LOAD_SIZE){
CP_LOGD("[DSP] WARNING: decompressed length [0x%.08x] unmatch with expected [0x%.08x].\r\n",outLen,DSP_LOAD_SIZE);
}
//dspbk.address = DspBackupAddress;
//dspbk.len = DSPBACKUP_SIZE;
//asr_property_set_param("dsp.backup.info",(const char *)&dspbk,sizeof(dsp_backup_info));
ret = 0;
}else{
CP_LOGE("\r\n ** ERROR: DSP image decompress failed .\r\n");
while(1);
}
}
cpy_dsp_by_cp=0;
}else{
cpy_dsp_by_cp=1;
ret = 0;
}
return ret;
}
#ifdef UNCOMPRESS_DEBUG
UINT32 CalcImageChecksum( UINT32* DownloadArea, UINT32 ImageLength,UINT32 checksum)
{
//uart_printf("CalcImageChecksum DownloadArea[%08x],ImageLength[%08x]\r\n",DownloadArea,ImageLength);
UINT32 ImageChecksum = checksum;
UINT32* ptr32 = DownloadArea;
UINT32* pEnd = ptr32 + (ImageLength / sizeof(UINT32));
UINT32 BytesSummed = 0;
while ( ptr32 < pEnd )
{
// checksum format version 2 algorithm as defined by flasher
ImageChecksum ^= (*ptr32);
ptr32++;
BytesSummed += sizeof(UINT32);
}
return ImageChecksum;
}
#endif
#if defined(ASR_PLATFORM_CRANEM)
int copy_rf_from_flash_to_psram(void)
{
//COPY rf.bin
unsigned int tmp;
_ptentry *rfEntry;
unsigned long magic;
unsigned long offset;
int outLen = -1;
CompressedType_e CompressedType;
UINT32 checksum = 0;
UINT32 rfbackupAddress = 0;
rfEntry = ptable_find_entry("rfbin");
rfbackupAddress = get_dsp_backup_end_addr();
rfLoadAddress = get_rf_load_addr();
rfFlashAddress = rfEntry->vstart;
rfCopySize = rfEntry->size;
uart_printf("copy_rf_from_flash_to_psram, rfFlashAddress=0x%x, rfCopySize=0x%x, rfLoadAddress=0x%x,\r\n",rfFlashAddress,rfCopySize,rfLoadAddress);
uart_printf("[RF ] copy from [0x%0.8x] to [0x%0.8x] size[0x%0.8x],backup[0x%0.8x]\r\n",
rfFlashAddress,
rfLoadAddress,
rfCopySize,
rfbackupAddress);
magic = *(volatile unsigned long*)rfFlashAddress;
CompressedType = GetCompressedType(magic);
if (LZMA == CompressedType)
{
//offset = rfLoadAddress - PSRAM_BASE_ADDRESS;
if(!LzmaUncompress((unsigned char *)rfbackupAddress + 8,(size_t *)&outLen, (const unsigned char *)rfFlashAddress, (size_t *)&rfCopySize))
{
*(volatile unsigned long*)rfbackupAddress = RFBIN_MAGIC;
*(volatile unsigned long*)(rfbackupAddress + 4) = outLen;
//checksum=CalcImageChecksum((UINT32 *)(rfbackupAddress + 8), outLen, 0);
uart_printf("[RF] released rf size [0x%.08x] inLen[0x%.08x] checksum[0x%.08x]\r\n", outLen,rfCopySize,checksum);
}else{
uart_printf("\r\n ** ERROR: RF image decompress failed .\r\n");
}
}else{
uart_printf("\r\n ** ERROR: RF image decompress failed .\r\n");
while(1);
}
return 0;
}
#else
int copy_rf_from_flash_to_psram(unsigned int rfFlashAddress,unsigned int rfCopySize,unsigned int rfLoadAddress)
{
//COPY rf.bin
unsigned long magic;
CompressedType_e CompressedType;
unsigned uncompress_size=0;
char *uncompress_buf=NULL;
int outLen = -1;
int dsp_non_bk_addr = -1;
unsigned int checksum = 0;
if(rfLoadAddress == INVALID_ADDRESS)
{
CP_LOGE("[RF ] rfLoadAddress = INVALID_ADDRESS\r\n");
while(1);
}
CP_LOGW("[RF ] copy from [0x%0.8x] to [0x%0.8x] size[0x%0.8x]\r\n",
rfFlashAddress,
rfLoadAddress,
rfCopySize);
magic = *(volatile unsigned long*)rfFlashAddress;
CompressedType = GetCompressedType(magic);
if (LZMA == CompressedType){
uncompress_size=get_LzmaUncompress_dst_size((const unsigned char *)rfFlashAddress);
uncompress_buf = (char *)malloc(uncompress_size);
if(uncompress_buf==NULL){
CP_LOGE("\r\n ** ERROR: copy RF image failed ,malloc failed[%08x]\r\n",uncompress_size);
while(1);
}
if(!LzmaUncompress((unsigned char *)uncompress_buf,(size_t *)&outLen, (const unsigned char *)rfFlashAddress, (size_t *)&rfCopySize))
{
CP_LOGD("[RF] Uncompress rf outLen [0x%.08x] inLen[0x%.08x]\r\n", outLen,rfCopySize);
if(uncompress_size!=outLen){
CP_LOGD("[RF] WARNING: decompressed length [0x%.08x] unmatch with expected [0x%.08x].\r\n",outLen,uncompress_size);
}
CP_LOGD("[RF] DspBackupAddress [0x%.08x]\r\n", DspBackupAddress);
if((DspLoadSize < (LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR)) && (CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH)){
if((outLen>CRANEL_SINGLE_RF_SIZE) && CHIP_IS_CRANEL){
rfLoadAddress = CRANEL_MULTI_RF_ADDRESS;
}
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),uncompress_buf,outLen);
CP_LOGD("[RF] copy rf to [0x%.08x] outLen[0x%.08x]\r\n",DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START), outLen);
}else if((CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH) && DspRamSize!=0){//this is 1606S 8M psram and all in dsp image
memcpy(DspBackupAddress+(CRANEL_4MRAM_RF_ADDRESS - PSRAM_DSP_START),uncompress_buf,outLen);
CP_LOGD("[RF] copy rf to [0x%.08x] outLen[0x%.08x]\r\n",DspBackupAddress+(CRANEL_4MRAM_RF_ADDRESS-PSRAM_DSP_START), outLen);
}
else{
dsp_non_bk_addr = (PSRAM_DSP_START + DSPBACKUP_SIZE);
if(rfLoadAddress>=dsp_non_bk_addr){
memcpy(rfLoadAddress,uncompress_buf,outLen);
}else{
if((rfLoadAddress + outLen)>dsp_non_bk_addr){
memcpy(dsp_non_bk_addr,uncompress_buf + (dsp_non_bk_addr - rfLoadAddress),(rfLoadAddress + outLen) - dsp_non_bk_addr);
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),uncompress_buf,(dsp_non_bk_addr - rfLoadAddress));
}else{
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),uncompress_buf,outLen);
}
}
}
free(uncompress_buf);
#ifdef UNCOMPRESS_DEBUG
checksum=CalcImageChecksum(DspBackupAddress,DSPBACKUP_SIZE,0);
checksum=CalcImageChecksum(dsp_non_bk_addr,DSP_LOAD_SIZE-DSPBACKUP_SIZE,checksum);
CP_LOGD("[RF ]copy rf SUCCEED,checksum[%08x]\r\n",checksum);
#else
CP_LOGD("[RF ]copy rf SUCCEED\r\n");
#endif
return 0;
}else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
while(1);
}
}
#ifdef CRANEL_CHIP
else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
while(1);
}
#endif
if(cpy_dsp_by_cp){
CP_LOGD("[RF ] copy rf by CP\r\n");
return 0;
}
{
if((DspLoadSize < (LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR)) && (CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH)){
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),rfFlashAddress,rfCopySize);
CP_LOGD("[RF] copy rf to [0x%.08x] rfCopySize[0x%.08x]\r\n",DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START), rfCopySize);
}else if((CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH) && DspRamSize != 0){//this is 1606S 8M psram and all in dsp image
memcpy(DspBackupAddress+(CRANEL_4MRAM_RF_ADDRESS - PSRAM_DSP_START),uncompress_buf,outLen);
CP_LOGD("[RF] copy rf to [0x%.08x] outLen[0x%.08x]\r\n",DspBackupAddress+(CRANEL_4MRAM_RF_ADDRESS-PSRAM_DSP_START), outLen);
}else{
dsp_non_bk_addr = (PSRAM_DSP_START + DSPBACKUP_SIZE);
if(rfLoadAddress>=dsp_non_bk_addr){
memcpy(rfLoadAddress,rfFlashAddress,rfCopySize);
}else{
if((rfLoadAddress + rfCopySize)>dsp_non_bk_addr){
memcpy(dsp_non_bk_addr,rfFlashAddress + (dsp_non_bk_addr - rfLoadAddress),(rfLoadAddress + rfCopySize) - dsp_non_bk_addr);
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),rfFlashAddress,(dsp_non_bk_addr - rfLoadAddress));
}else{
memcpy(DspBackupAddress+(rfLoadAddress-PSRAM_DSP_START),rfFlashAddress,rfCopySize);
}
}
}
#ifdef UNCOMPRESS_DEBUG
checksum=CalcImageChecksum(DspBackupAddress,DSPBACKUP_SIZE,0);
checksum=CalcImageChecksum(dsp_non_bk_addr,DSP_LOAD_SIZE-DSPBACKUP_SIZE,checksum);
CP_LOGD("[RF ]copy rf SUCCEED,checksum[%08x]\r\n",checksum);
#else
CP_LOGD("[RF ]copy rf SUCCEED\r\n");
#endif
/*
memcpy( (void *)rfLoadAddress,
(void *)rfFlashAddress,
rfCopySize);
tmp = memcmp((void*)rfLoadAddress,
(void*)rfFlashAddress,
rfCopySize);
uart_printf("[RF ]memcmp result %s\r\n",(tmp==0)?"SUCCEED":"FAILED");
*/
}
return 0;
}
#endif
//REDUCE_SULOG_IRBUF_DSP
int copy_rf_from_flash_to_psram_RSID(void)
{
//COPY rf.bin
unsigned int tmp;
_ptentry *rfEntry;
unsigned long magic;
unsigned long offset;
int outLen = -1;
CompressedType_e CompressedType;
UINT32 checksum = 0;
UINT32 rfbackupAddress = 0;
rfEntry = ptable_find_entry("rfbin");
rfbackupAddress = get_dsp_backup_end_addr();
rfFlashAddress = rfEntry->vstart;
rfCopySize = rfEntry->size;
CP_LOGD("[RF ] copy from [0x%0.8x] to [0x%0.8x] size[0x%0.8x],backup[0x%0.8x]\r\n",
rfFlashAddress,
rfLoadAddress,
rfCopySize,
rfbackupAddress);
magic = *(volatile unsigned long*)rfFlashAddress;
CompressedType = GetCompressedType(magic);
if (LZMA == CompressedType)
{
//offset = rfLoadAddress - PSRAM_BASE_ADDRESS;
if(!LzmaUncompress((unsigned char *)rfbackupAddress + 8,(size_t *)&outLen, (const unsigned char *)rfFlashAddress, (size_t *)&rfCopySize))
{
if((DspLoadSize == DSP_ALLIN_M1_SIZE) && (IsChipCraneL()||IsChipCraneLR())){
rfLoadAddress = get_rf_load_addr();
if((outLen>CRANEL_SINGLE_RF_SIZE) && CHIP_IS_CRANEL){
rfLoadAddress = CRANEL_MULTI_RF_ADDRESS;
}
memcpy(DspExecAddress+(rfLoadAddress-PSRAM_BASE_ADDRESS),(UINT32 *)(rfbackupAddress + 8),outLen);
}else{
*(volatile unsigned long*)rfbackupAddress = RFBIN_MAGIC;
*(volatile unsigned long*)(rfbackupAddress + 4) = outLen;
//checksum=CalcImageChecksum((UINT32 *)(rfbackupAddress + 8), outLen, 0);
}
CP_LOGD("[RF] released rf size [0x%.08x] inLen[0x%.08x] checksum[0x%.08x]\r\n", outLen,rfCopySize,checksum);
}else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
}
}else{
CP_LOGE("\r\n ** ERROR: RF image decompress failed .\r\n");
while(1);
}
return 0;
}
void PrepareToExecuteCp(void)
{
CP_LOGD("Decompress dsp and rw data start!\r\n");
unsigned int val;
_ptentry *cpEntry, *dspEntry,*rfEntry;
#ifdef DEBUG_LZMA
Timer0_enable(TRUE);
#endif
/* [NOTE] move these init code into logo as pm803 use */
/* printf the Chip ID */
CP_LOGD("chip id: 0x%.08x\r\n",GetLongChipID());
#ifndef LTEONLY_SINGLE_SIM
CpCoreFreqChangeTo624();
if(ifPsramLimit200M()){
PsramPhyFreqChangeTo350();
}else{
PsramPhyFreqChangeTo416();
}
#endif
enable_psram_cache();
dspEntry = ptable_find_entry("dsp");
rfEntry = ptable_find_entry("rfbin");
DspFlashAddress = dspEntry->vstart;
DspImageSize = dspEntry->vsize;
DspExecAddress = get_dsp_load_addr();
DspLoadSize = get_dsp_copy_size();
#if defined(ASR_PLATFORM_CRANEM)
if(decompress_dsp_from_flash_to_ddr()){
goto FAIL;
}
#else
if(copy_dsp_from_flash_to_psram((unsigned int *)&DspImageSize)){
goto FAIL;
}
#endif
#if defined(REDUCE_SULOG_IRBUF_DSP)
if(copy_rf_from_flash_to_psram_RSID()){
goto FAIL;
}
#else
if(CHIP_IS_CRANELS){
if(copy_rf_from_flash_to_psram_RSID()){
goto FAIL;
}
}else{
#if defined(ASR_PLATFORM_CRANEM)
if(copy_rf_from_flash_to_psram()){
goto FAIL;
}
#else
rfLoadAddress = get_rf_load_addr();
rfFlashAddress = rfEntry->vstart;
rfCopySize = rfEntry->vsize;
if(copy_rf_from_flash_to_psram(rfFlashAddress,rfCopySize,rfLoadAddress)){
goto FAIL;
}
#endif
}
#endif
CpExecAddress = get_cp_exec_addr(); //CP Exec Addr
CpCopySize = get_cp_copy_size();
//DEALING WITH CP.bin
if (get_cp_execute_mode() == XIP){
//execute mode = XIP && RW_COMPRESSED detected
region_decompress_from_flash_to_psram();
}
#ifndef LTEONLY_SINGLE_SIM
else
{
//execute mode = PSRAM
if(copy_cp_from_flash_to_psram()){
goto FAIL;
}
}
#endif
disable_psram_cache();
#ifndef LTEONLY_SINGLE_SIM
CpCoreFreqChangeTo416();
#endif
#ifdef DEBUG_LZMA
Timer0_enable(FALSE);
#endif
CP_LOGD("Decompress dsp and load rf data END!\r\n");
return;
FAIL:
CP_LOGE("PrepareToExecuteCp failed!\r\n");
while(1);
}
#endif
static char heap_a[LOGO_HEAP_SIZE];
void init_heap(void)
{
unsigned int val;
unsigned long DspBackupEndAddress;
#ifndef LTEONLY_SINGLE_SIM
DspLoadSize = get_dsp_copy_size();
val=get_ddr_heap_size();
DspBackupSize = get_dsp_backup_size();
if(val==0 || DspBackupSize==0){
CP_LOGE("loadtable not latest,heap size[%08x] dsp_bk size[%08x]!\r\n",val,DspBackupSize);
goto FAIL;
}
if(DspBackupSize>val){
CP_LOGE("dsp bk size too larger[%08x], heap size[%08x]!\r\n",DspBackupSize,val);
goto FAIL;
}
CP_LOGD("logo LOGO_IMG_END_ADDR[%08x]!\r\n",LOGO_IMG_END_ADDR);
DspBackupAddress = get_dsp_backup_addr();
if(DspBackupAddress==0){
CP_LOGE("loadtable not latest, DspBackupAddress error!!!\r\n");
goto FAIL;
}
if((DspLoadSize < (LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR)) && (CHIP_IS_CRANEL || CHIP_IS_CRANELS || CHIP_IS_CRANELR || CHIP_IS_CRANELG || CHIP_IS_CRANELRH)){
DspBackupEndAddress = get_dsp_backup_end_addr();
if(DspBackupAddress>=DspBackupEndAddress){
CP_LOGE("error!!!DspBackupAddress[%08x] DspBackupEndAddress[%08x]\r\n",DspBackupAddress,DspBackupEndAddress);
goto FAIL;
}
if((DspBackupEndAddress-DspBackupAddress + 4 )<(DspBackupSize)){
CP_LOGE("error!!!DspBackupAddress[%08x] DspBackupEndAddress[%08x] DspBackupSize[%08x]\r\n",DspBackupAddress,DspBackupEndAddress,DspBackupSize);
goto FAIL;
}
}else{
if((LOGO_IMG_END_ADDR-PSRAM_CONFIG_CACHE_START_ADDR)>DspBackupSize){
CP_LOGE("logo image too larger!\r\n");
goto FAIL;
}
}
#endif
/* support malloc mechanism */
malloc_init(heap_a, LOGO_HEAP_SIZE);
CP_LOGD("init_heap done!\r\n");
return;
FAIL:
CP_LOGE("init_heap failed!\r\n");
while(1);
}
extern unsigned int Load$$DATA$$RW$$Base;
extern unsigned int Image$$DATA$$RW$$Base;
extern unsigned int Image$$DATA$$RW$$Length;
void logo(void)
{
unsigned int val;
volatile UINT8 var;
unsigned int i;
UINT32 battery_level;
//[1] uart init
cp_uart_init();
CP_LOGD("LOGO START\r\n");
usticaInit();
unsigned int dst_addr=(unsigned int)&Image$$DATA$$RW$$Base;
unsigned int src_addr=(unsigned int)&Load$$DATA$$RW$$Base;
unsigned int len=(unsigned int)&Image$$DATA$$RW$$Length;
if((dst_addr < src_addr) && ((dst_addr+len) > src_addr)){
CP_LOGE("[LOGO] RW data overlap,Image:0x%08x,Load:0x%08x,len:%d\r\n",dst_addr,src_addr,len);
while(1);
}
/*[2] Print LOGO HEADER INFO */
CP_LOGW("[LOGO] VERSION_DATE :[%s]\r\n",(logo_vb.vb.logo_version_block.version_date));
CP_LOGD("LCD_TYPE:[%s]\r\n",logo_vb.vb.logo_version_block.oem_lcd_type);
CP_LOGD("ver:%s\r\n",logo_vb.vb.logo_version_block.build_info_string);
CP_LOGD("LOGO_FLAG:%s\r\n",logo_vb.FeedbackBlock.feedback_block.LogoDisplayLogoFlag);
#ifndef LTEONLY_SINGLE_SIM
asr_property_set("logo.version",logo_vb.vb.logo_version_block.build_info_string);
asr_property_set("logo.lcd_type",logo_vb.vb.logo_version_block.oem_lcd_type);
asr_property_set("logo.displayflag",logo_vb.FeedbackBlock.feedback_block.LogoDisplayLogoFlag);
#endif
asr_property_dump();
//[3] Enable MPU and using the cortex-r default memory map as the background region
reset_all_mpu_reg();
val = sctlr_get();
val |= SCTLR_BR | SCTLR_M;
sctlr_set(val);
//[4] MPU config
CP_LOGD("logo MPU config\r\n");
set_mpu_reg_background(1);//FULL_ACCESS
set_mpu_reg_itcm();
set_mpu_reg_dtcm();
set_mpu_reg_flash(0x01000000);//16M
set_mpu_reg_asic_reg();
set_mpu_reg_psram(0);
set_mpu_reg_background(0);//NO_ACCESS
mpu_value_check();
// PMIC_Init();
// sdcard_init();
#ifdef DEBUG_FLOAT_OPERATOR
/* Note :can execute float operation but can not printf float type data with %f */
CP_LOGD("test_float_data!\r\n");
test_float_data();
test_fitting_calculate();
#endif
#ifdef SUPPORT_MALLOC
/* support malloc mechanism */
malloc_init(g_MallocBuffer, MALLOC_BUFFER_SIZE);
CP_LOGD("malloc init done!\r\n");
#endif
/* [5] ptable init and dump */
if(ptable_init()){
CP_LOGE("bad partition table!\r\n");
while(1);
}
// ptable_dump();
/* 6] KEY PARTITION INFO FETCH */
GetKeyPartitionInfoFetch();
/* [7] flash and loadtable init */
bbu_qspi_init();
loadtable_init(CpFlashAddress);
init_heap();
logo_header_table_init();
//dump_loadtable();
#ifdef MRD_DEBUG_CODE
test_MRD_api();
#endif /* MRD_DEBUG_CODE */
#ifdef PM803_DEBUG_CODE
if( PMIC_IS_PM803() ){
LogoBattery_t BatteryRes;
unsigned short adcvol;
CP_LOGD("check battery level\r\n");
CheckBatteryLevel( &BatteryRes );
CP_LOGD("BatteryRes:%d\r\n",BatteryRes);
#ifdef CRANEL_CHIP //craneL ADC,1603没有这两个接口
CP_LOGD("check adc0 level\r\n");
ql_adc_read(0, &adcvol);
CP_LOGD("adc0Res:%d\r\n",adcvol);
CP_LOGD("check adc1 level\r\n");
ql_adc_read(1, &adcvol);
CP_LOGD("adc1Res:%d\r\n",adcvol);
#endif
}
#endif
#ifdef DMCHAGE
DM_CHARGE_Manager();
#endif
#ifdef QUEC_LCD_USR_FOR_LOGO
Vibrator_And_LogoFeedback();
//spi 回环测试
//quec_spi_test();
#else
#if 0//不再使用ASR的代码
/* check LOGO FLAG in logo.bin */
if(0 == strncmp(logo_vb.FeedbackBlock.feedback_block.LogoDisplayLogoFlag,ENABLE_LOGO_DISPLAY_FLAG,sizeof(ENABLE_LOGO_DISPLAY_FLAG))){
/* [8] Display logo and enable vibrator */
}else{
CP_LOGD("Read \"LOGO_FLAG\" from image is %s, not display logo\r\n",logo_vb.FeedbackBlock.feedback_block.LogoDisplayLogoFlag);
}
#endif
#endif
#ifdef QUEC_LOGO_GET_POWERUP_REASON
int reason,wake_reason;
reason = ql_get_powerup_reason();
uart_printf("=====logo powerup reason:%d====\r\n",reason);
wake_reason = SysRestartReasonGet();
uart_printf("==wake reason:%d, %c==\n", wake_reason,wake_reason);
#endif
/* [9] do some prepare work before executing cp.bin (e.g. decompress dsp, load rf. decompress cp_rw if necessary) */
PrepareToExecuteCp();
/* [10] return to boot33 */
//if(g_LzmaOptimizeFlag == TRUE){
// LzmaOptimizeSwitch(FALSE);
//}
CP_LOGD("LOGO END\r\n");
return;
//while(1);
}