#!/usr/bin/perl | |
# | |
# Copyright Statement: | |
# -------------------- | |
# This software is protected by Copyright and the information contained | |
# herein is confidential. The software may not be copied and the information | |
# contained herein may not be used or disclosed except with the written | |
# permission of MediaTek Inc. (C) 2006 | |
# | |
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES | |
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") | |
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON | |
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, | |
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF | |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. | |
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE | |
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR | |
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH | |
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO | |
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S | |
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. | |
# | |
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE | |
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, | |
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, | |
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO | |
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. | |
# | |
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE | |
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF | |
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND | |
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER | |
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). | |
# | |
#***************************************************************************** | |
#* | |
#* Filename: | |
#* --------- | |
#* emigenflash.pl | |
#* | |
#* Project: | |
#* -------- | |
#* | |
#* | |
#* Description: | |
#* ------------ | |
#* Parse and generate flash parameter | |
#* | |
#* Author: | |
#* ------- | |
#* Way Chen (mtk54483) | |
#* | |
#*============================================================================ | |
#* HISTORY | |
#* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! | |
#*------------------------------------------------------------------------------ | |
#* $Revision$ | |
#* $Modtime$ | |
#* $Log$ | |
#* | |
#* 05 22 2014 tafang.chen | |
#* [MOLY00062786] [UMOLY][SM] | |
#* Initial MoDIS build env - fix path problem. | |
#* | |
#* 04 23 2014 guo-huei.chang | |
#* [MOLY00062623] [UMOLY] update TK6291 emi | |
#* updat emigen flow for generating external emi size when EMI is not in MD own. | |
#* | |
#* 04 21 2014 guo-huei.chang | |
#* [MOLY00063203] [EMIGEN] Update EMIGEN for Smart Phone Project | |
#* Update emigen to generate EMI size for none EMI support | |
#* | |
#* | |
#*------------------------------------------------------------------------------ | |
#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! | |
#*============================================================================ | |
#****************************************************************************/ | |
my $nor_fat_base_offset; | |
my $nor_fat_size_offset; | |
my $nor_partition_sector_offset; | |
my $nor_nand_fat_base_offset; | |
my $nor_nand_fat_size_offset; | |
my $nor_nand_partition_sector_offset; | |
my $nfb_fat_base_offset; | |
my $nfb_fat_size_offset; | |
my $nfb_partition_sector_offset; | |
my $cmem_max_blocks = 0; | |
my $cmem_max_sectors = 0; | |
my $DebugPrint = 1; # 1 for debug; 0 for non-debug | |
#**************************************************************************** | |
# subroutine: Calculate_FAT_Info | |
# input: $info_list_href: input list reference of list of MDL info | |
# $combo_mem_count: number of memory devices selected | |
# $combo_sip_count: number of SIPs | |
# $mem_dev_type: MEMORY_DEVICE_TYPE | |
# $info_output_href: output hash reference for common MDL info, | |
# including minimum physical flash size, | |
# minimum small block start address | |
# maximum default FAT base address | |
# minimum default FAT size | |
# minimum RAM size | |
# common flash series information | |
# common single/multiple-bank definition | |
# common PBP information | |
# minimum PBP size | |
#**************************************************************************** | |
sub Calculate_FAT_Info | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $COMM_MDL_INFO_LOCAL, $MDL_INFO_LIST_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL,$nor_size_Mb_LOCAL, $CUSTOM_FEATURE_CFG_OPTIONS_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL) = @_; | |
### Print out the physical available flash size | |
my $flash_limit = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
#print "$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}, $COMM_MDL_INFO_LOCAL->{1}->{'Flash Size'}\n" if ($DebugPrint == 1); | |
### Calculate real FAT start address and size based on customization | |
if ((defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE})) | |
{ | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}); | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE}); | |
} | |
elsif ((defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (!defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE})) | |
{ | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__}) # for NOR FDM5, small blocks at the end of the flash should not be used | |
{ | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Small Block Start'} - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}); | |
} | |
else | |
{ | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}); | |
} | |
} | |
elsif ((!defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE})) | |
{ | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'}; | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE}); | |
} | |
else | |
{ | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'}; | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'}; | |
} | |
if($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'} = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL; | |
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'} = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL; | |
} | |
elsif($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS}); | |
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_SIZE}); | |
} | |
### work-around for bad small block issue | |
my $fat_size_shrink; | |
if ((($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)>$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}) && (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)<=($nor_size_Mb_LOCAL/8*1024*1024))) | |
{ | |
$fat_size_shrink = sprintf(" - 0x%08x", $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL-$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - ($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL-$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
} | |
#print "NOR_FLASH_BASE_ADDRESS_VAL = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, NOR_ALLOCATED_FAT_SPACE_VAL = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL\n" if ($DebugPrint == 1); | |
### Check FAT settings validity | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot exceed physical NOR flash size!", __FILE__, __LINE__) | |
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL<0) || ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL<0)); | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot exceed physical NOR flash size!", __FILE__, __LINE__) | |
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) > ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'})); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__}) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot include small blocks in NOR FDM 5.0!", __FILE__, __LINE__) | |
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) > $COMM_MDL_INFO_LOCAL->{0}->{'Small Block Start'}); | |
} | |
### FAT tuning for FOTA | |
$nor_fat_base_offset = "0x0"; | |
$nor_fat_size_offset = "0x0"; | |
$nor_partition_sector_offset = 0; | |
$nor_nand_fat_base_offset = "0x0"; | |
$nor_nand_fat_size_offset = "0x0"; | |
$nor_nand_partition_sector_offset = 0; | |
$nfb_fat_base_offset = "0x0"; | |
$nfb_fat_size_offset = "0x0"; | |
$nfb_partition_sector_offset = 0; | |
##FOTA Feature Related Code, Currently we do not use in MT6290 | |
if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM') | |
{ | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} ne 'NONE') | |
{ | |
### | |
# image head area size = block number * block size (0x20000) | |
# = (1(FOTA_BL_IMG_MAX_SIZE) + 6(FOTA_UE_RESIDENT_FLASH_SPACE_SIZE) + 6(FOTA_UE_BACKUP_FLASH_SPACE_SIZE) + 8(image list block) + 1(ext_bootloader) + 2(bad block margin)) * 0x20000 = 0x300000 | |
my $image_head_area_size = 0x300000; | |
my ($package_storage_base, $package_storage_size); | |
### | |
# FOTA_PACKAGE_STORAGE_BASE = image head area size + all ROM sizes (ROM, SECONDARY_ROM, THIRD_ROM, DEMAND_PAGING_ROM0) | |
if (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'ENFB') | |
{ | |
$package_storage_base = $image_head_area_size + 0x900000 + 0x1500000 + 0x800000; | |
} | |
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'ONDEMAND') | |
{ | |
$package_storage_base = $image_head_area_size + 0x400000 + 0xC00000 + 0xE00000; | |
} | |
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'MIXED') | |
{ | |
$package_storage_base = $image_head_area_size + 0x400000 + 0xF00000 + 0x800000 + 0x400000; | |
} | |
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'BASIC') | |
{ | |
$package_storage_base = $image_head_area_size + 0x800000 + 0x1600000; | |
} | |
$package_storage_size = (hex($CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_AREA_SIZE}) / 0x20000) * 0x20000; | |
my $recommend_fat_base; | |
if ($MAKEFILE_OPTIONS_LOCAL->{'secure_support'} eq 'TRUE') | |
{ | |
# When SECURE_SUPPORT = TRUE, FAT_BASE_ADDRESS = FOTA_PACKAGE_STORAGE_BASE + FOTA_PACKAGE_STORAGE_SIZE + ((4 + FOTA_EXTRA_RESERVED_BLOCKS) * (block size)0x20000) | |
$recommend_fat_base = $package_storage_base + $package_storage_size + ((4 + 5) * 0x20000); | |
} | |
else | |
{ | |
# When SECURE_SUPPORT = FALSE, FAT_BASE_ADDRESS = FOTA_PACKAGE_STORAGE_BASE + FOTA_PACKAGE_STORAGE_SIZE | |
$recommend_fat_base = $package_storage_base + $package_storage_size; | |
} | |
if (($recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})) > 0) | |
{ | |
$nfb_fat_base_offset = sprintf("0x%08X", $recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})); | |
$nfb_fat_size_offset = sprintf("0x%08X", $recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS}) | |
{ | |
my $nand_fat_partition_sectors; | |
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/) | |
{ | |
$nand_fat_partition_sectors = $1; | |
} | |
$nfb_partition_sector_offset = sprintf("%d", ($recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})) / 512) if (($nand_fat_partition_sectors - ($recommend_fat_base-hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS}))/512) >= 4096); # NAND user drive should be no less than 4096 sectors | |
} | |
} | |
} | |
elsif ($MAKEFILE_OPTIONS_LOCAL->{'system_drive_on_nand'} eq 'TRUE' or $MAKEFILE_OPTIONS_LOCAL->{'fota_update_package_on_nand'} eq 'TRUE') | |
{ | |
my $package_storage_size = (hex($CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_AREA_SIZE}) / 0x20000) * 0x20000; | |
$nor_nand_fat_base_offset = sprintf("0x%08X", $package_storage_size); | |
$nor_nand_fat_size_offset = sprintf("0x%08X", $package_storage_size); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS}) | |
{ | |
my $nand_fat_partition_sectors; | |
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/) | |
{ | |
$nand_fat_partition_sectors = $1; | |
} | |
$nor_nand_partition_sector_offset = sprintf("%d", $package_storage_size / 512) if (($nand_fat_partition_sectors - ($package_storage_size)/512) >= 4096); # NAND user drive should be no less than 4096 sectors | |
} | |
} | |
elsif (!exists $MAKEFILE_OPTIONS_LOCAL->{'emmc_booting'} or $MAKEFILE_OPTIONS_LOCAL->{'emmc_booting'} eq 'NONE') # FOTA update package will be put in a different partition from FS | |
{ | |
my $fota_block_number = $CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_BLOCK_NUMBER}; | |
my $ori_nor_flash_base_address_val = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL; | |
my $ori_nor_allocated_fat_space_val = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL; | |
### Package Storage | |
while ($fota_block_number > 0) | |
{ | |
my $tmp_block_sz; | |
$tmp_block_sz = &config_query_flash_block_sz($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $COMM_MDL_INFO_LOCAL,$ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL); | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL += $tmp_block_sz; | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL -= $tmp_block_sz; | |
$fota_block_number--; | |
} | |
### Backup Storage | |
my $query_address = 0; | |
my $max_block_size = 0; | |
while ($query_address < $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}) | |
{ | |
my $cur_block_size = &config_query_flash_block_sz($query_address, $COMM_MDL_INFO_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL); | |
if ($cur_block_size > $max_block_size) | |
{ | |
$max_block_size = $cur_block_size; | |
} | |
$query_address += $cur_block_size; | |
} | |
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL += 2 * $max_block_size; | |
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL -= 2 * $max_block_size; | |
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL - $ori_nor_flash_base_address_val) > 0) | |
{ | |
$nor_fat_base_offset = sprintf("0x%08X", $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL - $ori_nor_flash_base_address_val); | |
$nor_fat_size_offset = sprintf("0x%08X", $$ori_nor_allocated_fat_space_val - $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_FIRST_DRIVE_SECTORS}) | |
{ | |
my $nor_fat_partition_sectors; | |
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/) | |
{ | |
$nor_fat_partition_sectors = $1; | |
} | |
$nor_partition_sector_offset = sprintf("%d", ($ori_nor_allocated_fat_space_val - $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) / 512) if (($nor_fat_partition_sectors - ($ori_nor_allocated_fat_space_val-$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)/512) >= 128); # NOR user drive should be no less than 128 sectors | |
} | |
} | |
} | |
}##end if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM') | |
### Calculate TOTAL_BLOCKS and NOR_BLOCK_SIZE by different memory devices | |
$cmem_max_blocks = 0; | |
$cmem_max_sectors = 0; | |
$nor_block_size = 0; | |
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
my $mem_idx = $_; | |
my (@cur_regions, @cur_banks, @cur_blocks, @cur_new_regions, @cur_blocks_start, @cur_blocks_size); | |
my $cur_blocks_sum = 0; | |
my $cur_regions_sum = 0; | |
my $cur_total_blocks = 0; | |
my $cur_nor_block_size = 0; | |
my $cur_total_sectors = 0; | |
my $cur_sector_size = 0; | |
my $cur_bank_str = 0; | |
my $cur_block_str = 0; | |
$cur_sector_size = ($MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Comm. Series'} eq 'INTEL_SIBLEY') ? 0x400 : 0x200; | |
##MDL CS1 is flash, COMM MDL number 0 is flash info | |
@cur_regions = &split_info($MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Last Bank'}->{'Region'}); | |
$cur_bank_str = $MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Device Geometry'}->{'Bank Info.'}; | |
@cur_banks = &split_info($cur_bank_str); | |
$cur_block_str = $MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Device Geometry'}->{'Block Info.'}; | |
@cur_blocks = &split_info($cur_block_str); | |
for (0..$#cur_blocks) | |
{ | |
if ($cur_blocks[$_] =~ /\{(0x\w+),\s*(0x\w+)\}/) # match {0x0,0x10000} | |
{ | |
last if (hex($1) >= $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); # end block infor traversal when the flash end among all memories has been reached | |
push @cur_blocks_start, $1; | |
push @cur_blocks_size, $2; | |
} | |
} | |
push @cur_blocks_start, $flash_limit; | |
for (0..($#cur_blocks_start-1)) | |
{ | |
my $target_region = $cur_blocks_size[$_]; | |
my $tmp_block_count = 0; | |
print "$_: $target_region\n"if ($DebugPrint == 1); | |
while ($cur_blocks_sum < hex($cur_blocks_start[$_+1])) | |
{ | |
$cur_blocks_sum += hex($cur_blocks_size[$_]); | |
if ($cur_blocks_sum > $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL) | |
{ | |
$cur_regions_sum += hex($cur_blocks_size[$_]); | |
$tmp_block_count++; | |
} | |
last if ($cur_regions_sum >= $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL); | |
} | |
if ($tmp_block_count > 0) | |
{ | |
$cur_total_blocks += $tmp_block_count; | |
if (hex($target_region) > hex($cur_nor_block_size)) # Find the largest block size within FS | |
{ | |
$cur_nor_block_size = $target_region; | |
} | |
} | |
last if ($cur_regions_sum >= $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL); | |
} | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space must be multiples of blocks!", __FILE__, __LINE__) if ($cur_regions_sum > $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL); | |
### Calculate the current number of sectors | |
### S1 = ((NOR_ALLOCATED_FAT_SPACE - NOR_BLOCK_SIZEMCP1 * SNOR_ERASE_QUEUE_SIZE) / SECTOR_SIZE) | |
### NOR_ALLOCATED_FAT_SPACE := NOR_BOOTING_NOR_FS_SIZE | |
### SNOR_ERASE_QUEUE_SIZE := NOR_FDM4_ESB_PARAMETER_ERASE_QUEUE_SIZE or 5 (default value) | |
### NOR_SYSTEM_DRIVE_RESERVED_BLOCK := NOR_PARAMETER_SYSTEM_DRIVE_RESERVED_BLOCK or 3 (default value) | |
### NOR_BLOCK_SIZEMCP1 := The largest block size within FAT in MCP 1. | |
### SECTOR_SIZE: | |
### Sibley:=0x400 | |
### Non-Sibley := 0x200 | |
if ($MAKEFILE_OPTIONS_LOCAL->{'enhanced_single_bank_nor_flash_support'} eq 'TRUE') | |
{ | |
$cur_total_sectors = ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - (hex($cur_nor_block_size) * $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_FDM4_ESB_PARAMETER_ERASE_QUEUE_SIZE})) / $cur_sector_size; | |
} | |
else | |
{ | |
$cur_total_sectors = ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - (hex($cur_nor_block_size) * $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_PARAMETER_SYSTEM_DRIVE_RESERVED_BLOCK})) / $cur_sector_size; | |
} | |
print "FAT SPACE is: $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, BlockSize is: $cur_nor_block_size, SectorSize is $cur_sector_size\n"if ($DebugPrint == 1); | |
### Find the overall max TOTAL_BLOCKS and NOR_BLOCK_SIZE | |
if ($nor_block_size < hex($cur_nor_block_size)) | |
{ | |
$nor_block_size = hex($cur_nor_block_size); | |
} | |
if ($cmem_max_blocks < $cur_total_blocks) | |
{ | |
$cmem_max_blocks = $cur_total_blocks; | |
} | |
if ($cmem_max_sectors < $cur_total_sectors) | |
{ | |
$cmem_max_sectors = $cur_total_sectors; | |
} | |
} | |
print "TOTAL_BLOCKS > 127 , recommend enable FDM5.0 feature!\n" if ($cmem_max_blocks > 127); | |
} | |
#**************************************************************************** | |
# subroutine: Validate_FAT_NORRAWDISK_OVERLAP | |
# input: $info_list_href: input list reference of list of MDL info | |
# $combo_mem_count: number of memory devices selected | |
# $combo_sip_count: number of SIPs | |
# $mem_dev_type: MEMORY_DEVICE_TYPE | |
# $info_output_href: output hash reference for common MDL info, | |
# including minimum physical flash size, | |
# minimum small block start address | |
# maximum default FAT base address | |
# minimum default FAT size | |
# minimum RAM size | |
# common flash series information | |
# common single/multiple-bank definition | |
# common PBP information | |
# minimum PBP size | |
#**************************************************************************** | |
sub Validate_FAT_NORRAWDISK_OVERLAP | |
{ | |
my ($CUSTOM_MEM_DEV_OPTIONS_LOCAL, $COMM_MDL_INFO, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL) = @_; | |
my %dsk_layout_hash; | |
my @dsk_layout_sort_list; | |
$dsk_layout_hash{$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL} = $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL; | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS}) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk0 larger than physical NOR flash size!", __FILE__, __LINE__) | |
if ((hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})+hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_SIZE})) > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk0 the same base address as FAT!", __FILE__, __LINE__) | |
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS}) == $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL); | |
$dsk_layout_hash{hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_SIZE}); | |
} | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS}) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 larger than physical NOR flash size!", __FILE__, __LINE__) | |
if ((hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS})+hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_SIZE})) > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 the same base address as FAT!", __FILE__, __LINE__) | |
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS}) == $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL); | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 the same base address as NOR Raw Disk0!", __FILE__, __LINE__) | |
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS}) == hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})); | |
$dsk_layout_hash{hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS})} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_SIZE}); | |
} | |
foreach (sort {$a <=> $b} keys %dsk_layout_hash) | |
{ | |
push @dsk_layout_sort_list, $_; | |
} | |
foreach (1..$#dsk_layout_sort_list) | |
{ | |
error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: NOR Flash disk overlapping detected. Please check NOR Raw disk and FAT setting!", __FILE__, __LINE__) | |
if (($dsk_layout_sort_list[$_-1]+$dsk_layout_hash{$dsk_layout_sort_list[$_-1]}) > $dsk_layout_sort_list[$_]); | |
} | |
} | |
#**************************************************************************** | |
# subroutine: Calculate_NORRAWDISK_Region_Info | |
# input: $info_list_href: input list reference of list of MDL info | |
# $combo_mem_count: number of memory devices selected | |
# $combo_sip_count: number of SIPs | |
# $mem_dev_type: MEMORY_DEVICE_TYPE | |
# $info_output_href: output hash reference for common MDL info, | |
# including minimum physical flash size, | |
# minimum small block start address | |
# maximum default FAT base address | |
# minimum default FAT size | |
# minimum RAM size | |
# common flash series information | |
# common single/multiple-bank definition | |
# common PBP information | |
# minimum PBP size | |
#**************************************************************************** | |
sub Calculate_NORRAWDISK_Region_Info | |
{ | |
my ($CUSTOM_MEM_DEV_OPTIONS_LOCAL) = @_; | |
my (@regions_disk0, @regions_disk1); | |
for (0..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK_NUM}) | |
{ | |
my $nor_booting_nor_disk_base_address = sprintf("NOR_BOOTING_NOR_DISK%d_BASE_ADDRESS", $_); | |
my $nor_booting_nor_disk_size = sprintf("NOR_BOOTING_NOR_DISK%d_SIZE", $_); | |
my $nor_booting_nor_disk_index = $_; | |
#print "[$nor_booting_nor_disk_index] Nor Disk Base: $nor_booting_nor_disk_base_address\n"if ($DebugPrint == 1); | |
#print "[$nor_booting_nor_disk_index] Nor Disk Size: $nor_booting_nor_disk_size\n"if ($DebugPrint == 1); | |
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_base_address}) | |
{ | |
#print "RAW DISK Check!\n"if ($DebugPrint == 1); | |
for (0..($#entire_block_info_start_list-1)) | |
{ | |
my $target_region; | |
my $tmp_block_count = 0; | |
my $tmp_blocks_sum = 0; | |
my $tmp_regions_sum = 0; | |
while ($tmp_blocks_sum < $entire_block_info_start_list[$_+1]) | |
{ | |
$tmp_blocks_sum += $entire_block_info_size_list[$_]; | |
if ($tmp_blocks_sum > hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_base_address})) | |
{ | |
$tmp_regions_sum += $entire_block_info_size_list[$_]; | |
$target_region = sprintf("0x%X", $entire_block_info_size_list[$_]); | |
$tmp_block_count++; | |
} | |
if ($tmp_regions_sum >= hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_size})) | |
{ | |
last; | |
} | |
} | |
if ($tmp_block_count > 0) | |
{ | |
if ($nor_booting_nor_disk_index == 0) | |
{ | |
push @regions_disk0, "{$target_region,$tmp_block_count}"; | |
} | |
elsif ($nor_booting_nor_disk_index == 1) | |
{ | |
push @regions_disk1, "{$target_region,$tmp_block_count}"; | |
} | |
} | |
if ($tmp_regions_sum >= hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_size})) | |
{ | |
last; | |
} | |
} | |
} | |
} | |
} | |
#**************************************************************************** | |
# subroutine: get_common_MDL_info | |
# input: $info_list_href: input list reference of list of MDL info | |
# $combo_mem_count: number of memory devices selected | |
# $combo_sip_count: number of SIPs | |
# $mem_dev_type: MEMORY_DEVICE_TYPE | |
# $info_output_href: output hash reference for common MDL info, | |
# including minimum physical flash size, | |
# minimum small block start address | |
# maximum default FAT base address | |
# minimum default FAT size | |
# minimum RAM size | |
# common flash series information | |
# common single/multiple-bank definition | |
# common PBP information | |
# minimum PBP size | |
#**************************************************************************** | |
sub get_common_MDL_info | |
{ | |
#my ($info_list_href, $combo_mem_count, $combo_sip_count, $mem_dev_type, $info_output_href, $LPSDRAM_CHIP_SELECT_LOCAL, $MAKEFILE_OPTIONS, $CUSTOM_MEM_DEV_OPTIONS, $CUSTOM_MEMORY_DEVICE_HDR) = @_; | |
my ($info_list_href, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $info_output_href, $MAKEFILE_OPTIONS_LOCAL, $LPSDRAM_CHIP_SELECT_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $emi_is_existed) = @_; | |
my $combo_mem_count = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}; | |
my $combo_sip_count = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_SIP_ENTRY_COUNT}; | |
my $mem_dev_type = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE}; | |
my $platform = $MAKEFILE_OPTIONS_LOCAL->{'platform'}; | |
my $min_flash_size = 0xffffffff; | |
my $max_nand_block_size = 0; | |
my $min_small_block_start = 0xffffffff; | |
my $max_fat_base = 0; | |
my $min_fat_space = 0xffffffff; | |
my $Size_Mb_ram_min = 0xffffffff*8/1024/1024; # minimum size in "Size (Mb)" field for RAM | |
my $ADMUX_CS0; | |
my $ADMUX_CS1; | |
my $if_DRAM; | |
my $Comm_Series_CS0_all = '*'; # all "Comm. Series" information | |
my $Comm_Series_CS1_all = '*'; # all "Comm. Series" information | |
my $Bank_if_S = 'M'; # mark as 'S' if there is any device whose "Bank" field is 'S' | |
my $PBP_Y_N_if_Y = 'N'; # mark as 'N' if there is any device whose "PBP -> Y/N" field is 'N' | |
my $PBP_Size_W_min = 0xffffffff; # minimum size in "PBP -> Size(W)" field | |
my $Last_Bank_Region; # common "Last Bank -> Region" field | |
my $Geometry_Bank_Info; # common "Geometry -> Bank Info." field | |
my $Geometry_Block_Info; # common "Geometry -> Block Info." field | |
#print "Flash PN: $info_list_href->[1]->{1}->{'Part Number'}, $info_list_href->[1]->{1}->{'Flash Size'}\n"; | |
for (1..$combo_mem_count) | |
{ | |
### Find the smallest default FAT configuration among all MCPs | |
my $cur_flash_size = 0; # physical flash size (excluding bad small blocks for Toshiba) | |
my $cur_small_block_start = 0; # the starting location of small blocks at the end of a flash | |
my $cur_sum_of_regions = 0; # the sum of the regions in the last bank | |
my $cur_fat_base = 0; # default FAT base (physical flash size - last bank size) | |
my $cur_fat_space = 0; # default FAT size (last bank size) | |
my @cur_blocks_start; # list of Block Info starting addresses | |
my @cur_blocks_size; # list of Block Info sizes | |
my @cur_regions = &split_info($info_list_href->[$_]->{1}->{'Last Bank'}->{'Region'}); # list of Last Bank -> Region Info. | |
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'}; | |
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info. | |
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'}; | |
my @cur_blocks = &split_info($cur_block_str); # list of Block Info. | |
# Calculate default FAT size/start address (Last Bank) | |
for (0..$#cur_regions) # calculate the sum of last bank | |
{ | |
if ($cur_regions[$_] =~ /\{(0x\w+)\s*,\s*(\d+)\}/) # match {0x20000, 7} | |
{ | |
$cur_sum_of_regions += hex($1) * $2; | |
} | |
} | |
for (0..$#cur_banks) # calculate the physical flash size | |
{ | |
if ($cur_banks[$_] =~ /\{(0x\w+)\s*,\s*(\d+)\}/) # match {0x20000, 7} | |
{ | |
$cur_flash_size += hex($1) * $2; | |
$cur_small_block_start += hex($1) * $2; | |
} | |
} | |
if (($#cur_regions>0) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__})) # for NOR FDM5, small blocks at the end of the flash should be excluded | |
{ | |
if ($cur_blocks[$#cur_blocks] =~ /\{(0x\w+)\s*,\s*(0x\w+)\}/) # match {0xFF0000,0x2000} | |
{ | |
$cur_small_block_start = hex($1); | |
} | |
$cur_fat_space = $cur_sum_of_regions - ($cur_flash_size-$cur_small_block_start); | |
} | |
else | |
{ | |
$cur_fat_space = $cur_sum_of_regions; | |
} | |
$cur_fat_base = $cur_flash_size - $cur_sum_of_regions; | |
##MT6290 Operation | |
#if($platform eq 'MT6290') | |
#{ | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
if (defined $info_list_href->[$_]->{1}->{'NAND Size(MB)'})##Fill NAND Flash Size if NAND Flash is exist | |
{ | |
$cur_flash_size = $info_list_href->[$_]->{1}->{'NAND Size(MB)'} * 1024 * 1024; | |
} | |
else | |
{ | |
$cur_flash_size = 0xffffffff; | |
} | |
} | |
#} | |
# Temporarily store physical flash size, small block start, and default FAT size/base for future reference | |
$info_list_href->[$_]->{1}->{'Flash Size'} = $cur_flash_size; | |
$info_list_href->[$_]->{1}->{'Small Block Start'} = $cur_small_block_start; | |
$info_list_href->[$_]->{1}->{'Default FAT Base'} = $cur_fat_base; | |
$info_list_href->[$_]->{1}->{'Default FAT Size'} = $cur_fat_space; | |
#print "Flash PN: $info_list_href->[$_]->{1}->{'Part Number'}, FlashSize: $info_list_href->[$_]->{1}->{'Flash Size'}, SmallBlockStart: $info_list_href->[$_]->{1}->{'Small Block Start'}, FATBase: $info_list_href->[$_]->{1}->{'Default FAT Base'}, FATSize: $info_list_href->[$_]->{1}->{'Default FAT Size'}\n"if ($DebugPrint == 1); | |
# In order to speed-up, assume the largest FAT base will be smaller than the physical flash size first | |
# Find the largest FAT base | |
if ($max_fat_base < $cur_fat_base) | |
{ | |
$max_fat_base = $cur_fat_base; | |
} | |
# Find the smallest flash size | |
if ($min_flash_size > $cur_flash_size) | |
{ | |
$min_flash_size = $cur_flash_size; | |
} | |
# Find the smallest small block start | |
if ($min_small_block_start > $cur_small_block_start) | |
{ | |
$min_small_block_start = $cur_small_block_start; | |
} | |
### Find the minimum RAM size in Mb | |
my $cur_Size_Mb_ram = $info_list_href->[$_]->{0}->{'Density (Mb)'}; | |
if ($Size_Mb_ram_min > $cur_Size_Mb_ram) | |
{ | |
$Size_Mb_ram_min = $cur_Size_Mb_ram; | |
} | |
### Find common ADMUX definition | |
if ($info_list_href->[$_]->{0}->{'ADMUX'} =~ /YES/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS0 eq "NO"); | |
$ADMUX_CS0 = "YES"; | |
} | |
elsif ($info_list_href->[$_]->{0}->{'ADMUX'} =~ /NO/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS0 eq "YES"); | |
$ADMUX_CS0 = "NO"; | |
} | |
if ($info_list_href->[$_]->{1}->{'ADMUX'} =~ /YES/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS1 eq "NO"); | |
$ADMUX_CS1 = "YES"; | |
} | |
elsif ($info_list_href->[$_]->{1}->{'ADMUX'} =~ /NO/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS1 eq "YES"); | |
$ADMUX_CS1 = "NO"; | |
} | |
### Find common "DRAM" information | |
if ($info_list_href->[$_]->{1}->{'DRAM'} =~ /YES/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select DRAM/PSRAM at one time! Please change selected MCP!", __FILE__, __LINE__) if ($if_DRAM eq "NO"); | |
$if_DRAM = "YES"; | |
} | |
elsif ($info_list_href->[$_]->{1}->{'DRAM'} =~ /NO/i) | |
{ | |
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select DRAM/PSRAM at one time! Please change selected MCP!", __FILE__, __LINE__) if ($if_DRAM eq "YES"); | |
$if_DRAM = "NO"; | |
} | |
### Find common "Comm. Series" information | |
if ((defined $info_list_href->[$_]->{1}->{'Comm. Series'}) and ($info_list_href->[$_]->{1}->{'Comm. Series'} ne '*')) | |
{ | |
if ($Comm_Series_CS0_all eq '*') | |
{ | |
$Comm_Series_CS0_all = $info_list_href->[$_]->{1}->{'Comm. Series'}; | |
} | |
else | |
{ | |
$Comm_Series_CS0_all .= " $info_list_href->[$_]->{1}->{'Comm. Series'}"; | |
} | |
} | |
if ((defined $info_list_href->[$_]->{1}->{'Comm. Series'}) and ($info_list_href->[$_]->{1}->{'Comm. Series'} ne '*')) | |
{ | |
if ($Comm_Series_CS1_all eq '*') | |
{ | |
$Comm_Series_CS1_all = $info_list_href->[$_]->{1}->{'Comm. Series'}; | |
} | |
else | |
{ | |
$Comm_Series_CS1_all .= " $info_list_href->[$_]->{1}->{'Comm. Series'}"; | |
} | |
} | |
### Find common single/multiple-bank definition | |
if ($info_list_href->[$_]->{1}->{'Bank'} =~ /S/i) | |
{ | |
$Bank_if_S = 'S'; | |
} | |
### Find common PBP information | |
if ($info_list_href->[$_]->{1}->{'PBP'}->{'Y / N'} =~ /Y/i) | |
{ | |
$PBP_Y_N_if_Y = 'Y'; | |
} | |
#print "PBP1: $info_list_href->[$_]->{1}->{'PBP'}->{'Y / N'}, PBP2: $info_list_href->[$_]->{1}->{'PBP'}->{'Size (Byte)'}\n"if ($DebugPrint == 1); | |
### Find the minimum PBP size | |
my $cur_PBP_size_W = ($mem_dev_type eq 'NOR_RAM_MCP') ? ($info_list_href->[$_]->{0}->{'PBP'}->{'Size(W)'}) : ($info_list_href->[$_]->{1}->{'PBP'}->{'Size (Byte)'}/2); | |
if ($cur_PBP_size_W eq '*' or $cur_PBP_size_W eq 'x' or $cur_PBP_size_W eq ' ') | |
{ | |
$cur_PBP_size_W = 0; | |
} | |
if ($PBP_Size_W_min > $cur_PBP_size_W) | |
{ | |
$PBP_Size_W_min = $cur_PBP_size_W; | |
} | |
### Find the max block size | |
if (defined $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'}) | |
{ | |
if ($max_nand_block_size < $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'} * 1024) | |
{ | |
$max_nand_block_size = $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'} * 1024; | |
} | |
} | |
}##end for (1..$combo_mem_count) | |
### Work around when the FAT base is larger than some flash size | |
if (($max_fat_base > $min_flash_size) or ($max_fat_base > $min_small_block_start)) | |
{ | |
$max_fat_base = 0; | |
for (1..$combo_mem_count) | |
{ | |
if (($info_list_href->[$_]->{1}->{'Default FAT Base'} < $min_flash_size) and ($info_list_href->[$_]->{1}->{'Default FAT Base'} < $min_small_block_start) and ($max_fat_base < $info_list_href->[$_]->{1}->{'Default FAT Base'})) | |
{ | |
$max_fat_base = $info_list_href->[$_]->{1}->{'Default FAT Base'}; | |
} | |
} | |
} | |
$min_fat_space = $min_flash_size - $max_fat_base; | |
for (1..$combo_mem_count) | |
{ | |
my $cur_Size_Mb_ram; | |
$cur_Size_Mb_ram = $info_list_href->[$_]->{0}->{'Density (Mb)'}; | |
if ($Size_Mb_ram_min > $cur_Size_Mb_ram) | |
{ | |
$Size_Mb_ram_min = $cur_Size_Mb_ram; | |
} | |
} | |
$info_output_href->{0}->{'Flash Size'} = $min_flash_size; | |
$info_output_href->{0}->{'NAND Block Size(KB)'} = $max_nand_block_size / 1024; | |
$info_output_href->{0}->{'Small Block Start'} = $min_small_block_start; | |
$info_output_href->{0}->{'Default FAT Base'} = $max_fat_base; | |
$info_output_href->{0}->{'Default FAT Size'} = $min_fat_space; | |
$info_output_href->{1}->{'Size (Mb)'} = $Size_Mb_ram_min; | |
$info_output_href->{0}->{'ADMUX'} = $ADMUX_CS0; | |
$info_output_href->{1}->{'ADMUX'} = $ADMUX_CS1; | |
$info_output_href->{1}->{'DRAM'} = $if_DRAM; | |
$info_output_href->{0}->{'Comm. Series'} = $Comm_Series_CS0_all; | |
$info_output_href->{1}->{'Comm. Series'} = $Comm_Series_CS1_all; | |
$info_output_href->{0}->{'Bank'} = $Bank_if_S; | |
$info_output_href->{0}->{'PBP'}->{'Y / N'} = $PBP_Y_N_if_Y; | |
$info_output_href->{0}->{'PBP'}->{'Size(W)'} = $PBP_Size_W_min; | |
#print "FlashSize[0] is $info_output_href->{0}->{'Flash Size'}, FlashSize[1] is $info_output_href->{1}->{'Flash Size'}\n"if ($DebugPrint == 1); | |
#print "NANDBlockSize[0] is $info_output_href->{0}->{'NAND Block Size(KB)'}, NANDBlockSize[1] is $info_output_href->{1}->{'NAND Block Size(KB)'}\n"if ($DebugPrint == 1); | |
#print "SmallBlockStart[0] is $info_output_href->{0}->{'Small Block Start'}, SmallBlockStart[1] is $info_output_href->{1}->{'Small Block Start'}\n"if ($DebugPrint == 1); | |
#print "DefaultFATBase[0] is $info_output_href->{0}->{'Default FAT Base'}, DefaultFATBase[1] is $info_output_href->{1}->{'Default FAT Base'}\n"if ($DebugPrint == 1); | |
#print "DefaultFATSize[0] is $info_output_href->{0}->{'Default FAT Size'}, DefaultFATSize[1] is $info_output_href->{1}->{'Default FAT Size'}\n"if ($DebugPrint == 1); | |
#print "Size[0] is $info_output_href->{0}->{'Size (Mb)'}, Size[1] is $info_output_href->{1}->{'Size (Mb)'}\n"if ($DebugPrint == 1); | |
#print "ADMUX[0] is $info_output_href->{0}->{'ADMUX'}, ADMUX[1] is $info_output_href->{1}->{'ADMUX'}\n"if ($DebugPrint == 1); | |
#print "DRAM[0] is $info_output_href->{0}->{'DRAM'}, DRAM[1] is $info_output_href->{1}->{'DRAM'}\n"if ($DebugPrint == 1); | |
#print "CommSeries[0] is $info_output_href->{0}->{'Comm. Series'}, CommSeries[1] is $info_output_href->{1}->{'Comm. Series'}\n"if ($DebugPrint == 1); | |
#print "Bank[0] is $info_output_href->{0}->{'Bank'}, Bank[1] is $info_output_href->{1}->{'Bank'}\n"if ($DebugPrint == 1); | |
#print "PBPYN[0] is $info_output_href->{0}->{'PBP'}->{'Y / N'}, PBPYN[1] is $info_output_href->{1}->{'PBP'}->{'Y / N'}\n"if ($DebugPrint == 1); | |
#print "PBPSize[0] is $info_output_href->{0}->{'PBP'}->{'Size(W)'}, PBPSize[1] is $info_output_href->{1}->{'PBP'}->{'Size(W)'}\n"if ($DebugPrint == 1); | |
} | |
#**************************************************************************** | |
# subroutine: get_common_MDL_Geo_info | |
# input: $info_list_href: input list reference of list of MDL info | |
# $combo_count: number of memory devices selected | |
# $mem_dev_type: MEMORY_DEVICE_TYPE | |
# $baseaddr: base address where the geometry list starts | |
# $endaddr: end address where the geometry list ends | |
# $region_info_size_href: list reference of common RegionInfo of the specified area (Size) | |
# $region_info_count_href: list of common RegionInfo of the specified area (Count) | |
# $bank_info_size_href: list of common BankInfo of the specified area (Size) | |
# $bank_info_count_href: list of common BankInfo of the specified area (Count) | |
#**************************************************************************** | |
sub get_common_MDL_Geo_info | |
{ | |
my ($info_list_href, $combo_count, $mem_dev_type, $baseaddr, $endaddr, $region_info_size_href, $region_info_count_href, $bank_info_size_href, $bank_info_count_href) = @_; | |
my ($prev_addr, $curr_addr, $idx); | |
### Get common RegionInfo | |
$prev_addr = $baseaddr; | |
$curr_addr = $baseaddr; | |
$idx = 0; | |
while ($curr_addr < $endaddr) # traverse till the endaddr | |
{ | |
### Find the largest block/bank offset from the current address to the next boundary | |
### Stop if the end of BankInfo or RegionInfo has been reached | |
my $largest_offset = 0; # largest offset from curr_addr to the next block/bank boundary | |
my $common_size = 0; # final(common) block/bank size of this round | |
my $size; # current offset from curr_addr to the next block/bank boundary | |
my $cur_combo_idx; | |
for (1..$combo_count) | |
{ | |
$cur_combo_idx = $_; | |
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'}; | |
my @cur_blocks = &split_info($cur_block_str); # list of Block Info. | |
my @cur_entire_regions = &convert_blocks_to_regions(\@cur_blocks, $endaddr); # list of Region Info. (of the entire flash) | |
my (@cur_entire_regions_size, @cur_entire_regions_count); | |
&convert_geo_hash_from_list(\@cur_entire_regions, \@cur_entire_regions_size, \@cur_entire_regions_count); | |
### Get the offset to the next boundary | |
$size = &get_next_Geo_boundary(\@cur_entire_regions_size, \@cur_entire_regions_count, $curr_addr); | |
last if ($size == 0); # reach the end of RegionInfo/BankInfo | |
if ($size > $largest_offset) | |
{ | |
$largest_offset = $size; | |
} | |
} | |
last if ($cur_combo_idx != $combo_count); # early break in for loop represents end of RegionInfo/BankInfo is reached | |
### Check whether curr_address+largest_offset is still on the boundaries of all MCPs | |
for (1..$combo_count) | |
{ | |
$cur_combo_idx = $_; | |
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'}; | |
my @cur_blocks = &split_info($cur_block_str); # list of Block Info. | |
my @cur_entire_regions = &convert_blocks_to_regions(\@cur_blocks, $endaddr); # list of Region Info. (of the entire flash) | |
my (@cur_entire_regions_size, @cur_entire_regions_count); | |
&convert_geo_hash_from_list(\@cur_entire_regions, \@cur_entire_regions_size, \@cur_entire_regions_count); | |
last if (&query_if_Geo_boundary(\@cur_entire_regions_size, \@cur_entire_regions_count, $curr_addr+$largest_offset) != 1); | |
} | |
# The address is not on the boundaries of all MCPs, need to go to the next address | |
# The next address is curr_addr + largest_offset | |
if ($cur_combo_idx != $combo_count) | |
{ | |
$curr_addr += $largest_offset; | |
next; | |
} | |
### Add the address into the output RegionInfo/BankInfo | |
# Get the size of common block/bank size | |
$common_size = $curr_addr + $largest_offset - $prev_addr; | |
if ($prev_addr == $baseaddr) # the first entry | |
{ | |
$region_info_size_href->[0] = $common_size; | |
$region_info_count_href->[0] = 1; | |
} | |
elsif ($common_size == $region_info_size_href->[$idx]) # the size is identical to the last bank we added --> count + 1 | |
{ | |
$region_info_count_href->[$idx]++; | |
} | |
else # tje soze os different from the last bank we added --> append new entry | |
{ | |
$idx++; | |
$region_info_size_href->[$idx] = $common_size; | |
$region_info_count_href->[$idx] = 1; | |
} | |
### Increment the current address and then perform the loop again | |
$curr_addr += $largest_offset; | |
$prev_addr = $curr_addr; | |
} | |
print "pass block info\n"; | |
### Get common BankInfo | |
$prev_addr = $baseaddr; | |
$curr_addr = $baseaddr; | |
$idx = 0; | |
while ($curr_addr < $endaddr) # traverse till the endaddr | |
{ | |
### Find the largest block/bank offset from the current address to the next boundary | |
### Stop if the end of BankInfo or RegionInfo has been reached | |
my $largest_offset = 0; # largest offset from curr_addr to the next block/bank boundary | |
my $common_size = 0; # final(common) block/bank size of this round | |
my $size; # current offset from curr_addr to the next block/bank boundary | |
my $cur_combo_idx; | |
for (1..$combo_count) | |
{ | |
$cur_combo_idx = $_; | |
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'}; | |
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info. | |
my (@cur_banks_size, @cur_banks_count); | |
&convert_geo_hash_from_list(\@cur_banks, \@cur_banks_size, \@cur_banks_count); | |
### Get the offset to the next boundary | |
$size = &get_next_Geo_boundary(\@cur_banks_size, \@cur_banks_count, $curr_addr); | |
last if ($size == 0); # reach the end of RegionInfo/BankInfo | |
if ($size > $largest_offset) | |
{ | |
$largest_offset = $size; | |
} | |
} | |
last if ($cur_combo_idx != $combo_count); # early break in for loop represents end of RegionInfo/BankInfo is reached | |
### Check whether curr_address+largest_offset is still on the boundaries of all MCPs | |
for (1..$combo_count) | |
{ | |
$cur_combo_idx = $_; | |
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'}; | |
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info. | |
my (@cur_banks_size, @cur_banks_count); | |
&convert_geo_hash_from_list(\@cur_banks, \@cur_banks_size, \@cur_banks_count); | |
last if (&query_if_Geo_boundary(\@cur_banks_size, \@cur_banks_count, $curr_addr+$largest_offset) != 1); | |
} | |
# The address is not on the boundaries of all MCPs, need to go to the next address | |
# The next address is curr_addr + largest_offset | |
if ($cur_combo_idx != $combo_count) | |
{ | |
$curr_addr += $largest_offset; | |
next; | |
} | |
### Add the address into the output RegionInfo/BankInfo | |
# Get the size of common block/bank size | |
$common_size = $curr_addr + $largest_offset - $prev_addr; | |
if ($prev_addr == $baseaddr) # the first entry | |
{ | |
$bank_info_size_href->[0] = $common_size; | |
$bank_info_count_href->[0] = 1; | |
} | |
elsif ($common_size == $bank_info_size_href->[$idx]) # the size is identical to the last bank we added --> count + 1 | |
{ | |
$bank_info_count_href->[$idx]++; | |
} | |
else # tje soze os different from the last bank we added --> append new entry | |
{ | |
$idx++; | |
$bank_info_size_href->[$idx] = $common_size; | |
$bank_info_count_href->[$idx] = 1; | |
} | |
### Increment the current address and then perform the loop again | |
$curr_addr += $largest_offset; | |
$prev_addr = $curr_addr; | |
} | |
} | |
#**************************************************************************** | |
# subroutine: get_next_Geo_boundary | |
# input: $geo_size_list_href: input list reference of geometry (Size list) | |
# $geo_count_list_href: input list reference of geometry (Size list) | |
# $addr: current address from which to query next boundary | |
# output: $size: size from current address to the next boundary | |
#**************************************************************************** | |
sub get_next_Geo_boundary | |
{ | |
my ($geo_size_list_href, $geo_count_list_href, $addr) = @_; | |
my $size; | |
### for all {Size, Count} pairs | |
for (0..$#$geo_size_list_href) | |
{ | |
### Treat the address as a pile of blocks. Remove them region by region. | |
if (($geo_size_list_href->[$_]*$geo_count_list_href->[$_]) <= $addr) | |
{ | |
$addr -= $geo_size_list_href->[$_]*$geo_count_list_href->[$_]; | |
next; | |
} | |
### Blocks that cannot fit-into one region. | |
# 1. We have found the region that addr belongs to. | |
# 2. The addr is aligned, if (addr % Size[$_]) equals 0. | |
# 3. The offset to the next boundary is (Size[$_] - (addr % Size[$_])) | |
return ($geo_size_list_href->[$_] - ($addr % $geo_size_list_href->[$_])); | |
} | |
return 0; | |
} | |
#**************************************************************************** | |
# subroutine: query_if_Geo_boundary | |
# input: $geo_size_list_href: input list reference of geometry (Size list) | |
# $geo_count_list_href: input list reference of geometry (Size list) | |
# $addr: address to be checked whether it is on the boundary or not | |
# output: $is_boundary: 1 if the queried address is on the boundary of all MCPs | |
#**************************************************************************** | |
sub query_if_Geo_boundary | |
{ | |
my ($geo_size_list_href, $geo_count_list_href, $addr) = @_; | |
my $ret; | |
### for all {Size, Count} pairs | |
for (0..$#$geo_size_list_href) | |
{ | |
### Treat the address as a pile of blocks. Remove them region by region. | |
if (($geo_size_list_href->[$_]*$geo_count_list_href->[$_]) <= $addr) | |
{ | |
$addr -= $geo_size_list_href->[$_]*$geo_count_list_href->[$_]; | |
next; | |
} | |
### Blocks that cannot fit-into one region. | |
# 1. We have found the region that addr belongs to. | |
# 2. The addr is aligned, if (addr % Size[$_]) equals 0. | |
# 3. The offset to the next boundary is (Size[$_] - (addr % Size[$_])) | |
if (($addr % $geo_size_list_href->[$_]) != 0) | |
{ | |
return 0; | |
} | |
} | |
return 1; | |
} | |
#**************************************************************************** | |
# subroutine: split_info | |
# return: List of RegionInfo/BlockInfo/BankInfo | |
# input: $info: Excel value to be split | |
#**************************************************************************** | |
sub split_info | |
{ | |
my ($info) = @_; | |
my $ret_str; | |
my @ret_info; | |
if ($info eq '*') | |
{ | |
push @ret_info, $info; | |
return @ret_info; | |
} | |
while ($info =~ /\{(0x\w+)\s*,\s*(\w+)\}/) | |
{ | |
$ret_str = "{" . $1 . "," . $2 . "}"; | |
push @ret_info, $ret_str; | |
$info = $'; | |
} | |
return @ret_info; | |
} | |
#**************************************************************************** | |
# subroutine: split_sfi_driving | |
# return: List of SFI driving | |
# input: $driving_str: Excel value to be split | |
#**************************************************************************** | |
sub split_sfi_driving | |
{ | |
my ($driving_str) = @_; | |
my @ret_driving; | |
$driving_str =~ s/\{//; # remove parentheses | |
$driving_str =~ s/\}//; # remove parentheses | |
$driving_str =~ s/\s+//g; # remove spaces | |
### parse the driving string | |
my $saved_sep = $/; | |
undef $/; | |
@ret_driving = split(/\,/, $driving_str); | |
$/ = $saved_sep; | |
return @ret_driving; | |
} | |
#**************************************************************************** | |
# subroutine: split_sfi_command | |
# return: List of SFI commands | |
# input: $command_str: Excel value to be split | |
#**************************************************************************** | |
sub split_sfi_command | |
{ | |
my ($command_str) = @_; | |
my @ret_command; | |
while ($command_str =~ /(\{.+\})/) | |
{ | |
my $tmp_str = $1; | |
$command_str = $'; | |
$tmp_str =~ s/\{//; # remove parentheses | |
$tmp_str =~ s/\}//; # remove parentheses | |
$tmp_str =~ s/\s+//g; # remove spaces | |
### parse the driving string | |
my $saved_sep = $/; | |
undef $/; | |
my @tmp_list = split(/\,/, $tmp_str); | |
$/ = $saved_sep; | |
### for commands {SPI, 0x35}, output "SPI, 1, 0x35", where 1 is the number of commands | |
if ($tmp_list[0] eq 'SPI' or $tmp_list[0] eq 'QPI') | |
{ | |
push @ret_command, $tmp_list[0]; | |
push @ret_command, $#tmp_list; | |
for (1..$#tmp_list) | |
{ | |
push @ret_command, $tmp_list[$_]; | |
} | |
} | |
else | |
{ | |
&error_handler("$MEMORY_DEVICE_LIST_XLS_E: Unknown SFI commands $command_str!", __FILE__, __LINE__); | |
} | |
} | |
return @ret_command; | |
} | |
#**************************************************************************** | |
# subroutine: region_info | |
# return: template of part "configure flash memory for FAT" | |
#**************************************************************************** | |
sub region_info | |
{ | |
my ($region_size_href, $region_count_href, $naming, $newline) = @_; | |
my $region_info_lines; | |
for (0..$#$region_size_href) | |
{ | |
my $tmp_size = sprintf("0x%X", $region_size_href->[$_]); | |
my $tmp_count = sprintf("%d", $region_count_href->[$_]); | |
if ($_ == $#$region_size_href) | |
{ | |
$region_info_lines .= " \{$tmp_size, $tmp_count\},\n"; | |
} | |
else | |
{ | |
$region_info_lines .= " \{$tmp_size, $tmp_count\}, \\$newline\n"; | |
} | |
} | |
chomp $region_info_lines; | |
if (!defined $naming) | |
{ | |
return $region_info_lines; | |
} | |
### | |
my $template; | |
if (defined $newline) | |
{ | |
$template .= <<"__TEMPLATE"; | |
$region_info_lines | |
__TEMPLATE | |
return $template; | |
} | |
my $naming_str = sprintf("$naming\[\]"); | |
if ($naming eq 'oriRegionInfo') | |
{ | |
$template .= <<"__TEMPLATE"; | |
FLASH_REGIONINFO_VAR_MODIFIER FlashRegionInfo $naming_str = | |
{ | |
$region_info_lines | |
EndoriRegionInfo | |
}; | |
__TEMPLATE | |
} | |
else | |
{ | |
$template .= <<"__TEMPLATE"; | |
#define $naming $region_info_lines | |
__TEMPLATE | |
} | |
chomp $template; | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: block_info | |
# return: template of part "configure flash memory for FAT" | |
# input: $tmp_blocks: Block Info | |
# $newline: whether there exists newline character and comments in the output Block Info string | |
#**************************************************************************** | |
sub block_info | |
{ | |
my ($block_start_href, $block_size_href, $newline) = @_; | |
my $block_info_lines; | |
for (0..$#$block_start_href) | |
{ | |
my $tmp_start = sprintf("0x%X", $block_start_href->[$_]); | |
my $tmp_size = sprintf("0x%X", $block_size_href->[$_]); | |
if ($_ == $#$block_start_href) | |
{ | |
$block_info_lines .= " \{$tmp_start, $tmp_size\},\n"; | |
} | |
else | |
{ | |
$block_info_lines .= " \{$tmp_start, $tmp_size\}, $newline\n"; | |
} | |
} | |
chomp $block_info_lines; | |
### | |
my $template; | |
if (defined $newline) | |
{ | |
$template .= <<"__TEMPLATE"; | |
$block_info_lines | |
__TEMPLATE | |
} | |
else | |
{ | |
$template .= <<"__TEMPLATE"; | |
/* | |
FLASH_REGIONINFO_VAR_MODIFIER FlashBlockTBL NOTREADYYET[] = | |
{ | |
$block_info_lines | |
EndBlockInfo | |
}; | |
*/ | |
__TEMPLATE | |
} | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: bank_info | |
# return: template of part "configure flash memory for FAT" | |
# input: $bank_size_href: Bank Info size | |
# $bank_count_href: Bank Info count | |
# $offset: the offset to start counting bank | |
# $target_size: the size of the FAT | |
# $newline: whether there exists newline character and comments in the output Bank Info string | |
#**************************************************************************** | |
sub bank_info | |
{ | |
my ($bank_size_href, $bank_count_href, $offset, $target_size, $newline) = @_; | |
my $template; | |
if (defined $newline) | |
{ | |
for (0..$#$bank_size_href) | |
{ | |
my $tmp_size = sprintf("0x%X", $bank_size_href->[$_]); | |
my $tmp_count = sprintf("%d", $bank_count_href->[$_]); | |
if ($_ == $#$bank_size_href) | |
{ | |
$template .= " \{$tmp_size, $tmp_count\},\n"; | |
} | |
else | |
{ | |
$template .= " \{$tmp_size, $tmp_count\}, $newline\n"; | |
} | |
} | |
return $template; | |
} | |
for (0..$#$bank_size_href) | |
{ | |
my $tmp_size = sprintf("0x%X", $bank_size_href->[$_]); | |
my $tmp_count = sprintf("%d", $bank_count_href->[$_]); | |
my $segment = ( hex($tmp_size) * $tmp_count ); | |
if ($offset <= 0) | |
# Bank already in | |
{ | |
if ($target_size >= $segment) | |
# Bank full in-used | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s \\ \n", hex($tmp_size), $tmp_count); | |
} | |
elsif ($target_size > 0) | |
# Bank partial used | |
{ | |
my $tmp = int($target_size / hex($tmp_size));; | |
if ( int($target_size / hex($tmp_size)) > 0 ) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", hex($tmp_size), int($target_size / hex($tmp_size)) ); | |
$target_size -= hex($tmp_size) * int($target_size / hex($tmp_size)); | |
} | |
if ($target_size > 0) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", $target_size , 1 ); | |
} | |
} | |
else | |
# Bank discarded | |
{ | |
} | |
$target_size -= $segment; | |
} | |
elsif ($offset < $segment) | |
# Segment cross the FAT Baseaddr | |
{ | |
my $c = $tmp_count; | |
while ($offset >= hex($tmp_size)) | |
{ | |
$c--; | |
$offset -= hex($tmp_size); | |
} | |
# Bank partial in-used | |
if ($offset > 0 and (hex($tmp_size) - $offset) >= $target_size) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", $target_size, 1); | |
$target_size -= hex($tmp_size); | |
$c--; | |
} | |
elsif ($offset > 0) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", (hex($tmp_size) - $offset), 1); | |
$target_size -= (hex($tmp_size) - $offset); | |
$c--; | |
} | |
# discount $offset and make $offset to negative value | |
$offset -= hex($tmp_size); | |
next if ($c == 0); # already last one bank on the FAT boundary | |
if ($target_size >= (hex($tmp_size) * $c)) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", hex($tmp_size), $c); | |
$target_size -= (hex($tmp_size) * $c); | |
} | |
elsif ($target_size > 0) | |
{ | |
if ( int($target_size / hex($tmp_size)) > 0 ) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", hex($tmp_size), int($target_size / hex($tmp_size)) ); | |
$target_size -= hex($1) * int($target_size / hex($tmp_size)); | |
} | |
if ($target_size > 0) | |
{ | |
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", $target_size , 1 ); | |
} | |
} | |
} | |
# No output and down counting to reach FAT Baseaddr | |
else | |
{ | |
$offset -= $segment; | |
} | |
} | |
$template = " {x , x},\n" if not defined $template; | |
chomp($template); | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: convert_blocks_to_regions | |
# return: RegionInfo of the entire flash, in {size, count} format instead of {start, size} format | |
# input: $tmp_blocks: input list of blocks | |
# output: @regions: output list of regions | |
#**************************************************************************** | |
sub convert_blocks_to_regions | |
{ | |
my ($tmp_blocks, $endaddr) = @_; | |
my @regions; | |
my ($cur_reg_start, $cur_block_size, $prev_reg_start, $prev_block_size); | |
for (0..$#$tmp_blocks) | |
{ | |
if ($tmp_blocks->[$_] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7} | |
{ | |
$cur_reg_start = hex($1); | |
$cur_block_size = hex($2); | |
} | |
if ($_ > 0) | |
{ | |
if ($tmp_blocks->[$_-1] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7} | |
{ | |
$prev_reg_start = hex($1); | |
$prev_block_size = hex($2); | |
} | |
my $tmp_region_info_line = sprintf("\{0x%X,%d\}", $prev_block_size, ($cur_reg_start-$prev_reg_start)/$prev_block_size); | |
push @regions, $tmp_region_info_line; | |
} | |
} | |
my $tmp_region_info_line; | |
if ($#$tmp_blocks >= 0) | |
{ | |
$tmp_region_info_line = sprintf("\{0x%X,%d\}", $cur_block_size, ($endaddr-$cur_reg_start)/$cur_block_size); | |
} | |
push @regions, $tmp_region_info_line; | |
return @regions; | |
} | |
#**************************************************************************** | |
# subroutine: convert_regions_to_blocks | |
# return: BlockInfo of the input RegionInfo, in {start, size} format instead of {size, count} format | |
# input: $regions_start: start address of region info | |
# $tmp_regions_size_list: input list of regions size | |
# $tmp_regions_count_list: input list of regions count | |
# output: $output_blocks_start_list: output list of blocks start | |
# $output_blocks_size_list: output list of blocks size | |
#**************************************************************************** | |
sub convert_regions_to_blocks | |
{ | |
my ($regions_start, $tmp_regions_size_list, $tmp_regions_count_list, $output_blocks_start_list, $output_blocks_size_list) = @_; | |
my @ret_blocks; | |
my $idx = 0; | |
$output_blocks_start_list->[0] = $regions_start; | |
for (0..$#$tmp_regions_size_list) | |
{ | |
$idx = $_; | |
# the block size is identical to the region block size | |
$output_blocks_size_list->[$_] = $tmp_regions_size_list->[$_]; | |
# the offset equals to the accumulated size of former regions | |
if ($_ != $#$tmp_regions_size_list) | |
{ | |
$output_blocks_start_list->[$_+1] = $output_blocks_start_list->[$_] + ($tmp_regions_size_list->[$_]*$tmp_regions_count_list->[$_]); | |
} | |
} | |
} | |
#**************************************************************************** | |
# subroutine: convert_geo_hash_from_list | |
# return: lists of flash geometry in {size, count} format | |
# input: $list_href: input list of blocks/banks | |
# $geo_size_list_output_href: Size part of flash geometry pairs | |
# $geo_count_list_output_href: Count part of flash geometry pairs | |
#**************************************************************************** | |
sub convert_geo_hash_from_list | |
{ | |
my ($list_href, $geo_size_list_output_href, $geo_count_list_output_href) = @_; | |
for (0..$#$list_href) | |
{ | |
if ($list_href->[$_] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7} | |
{ | |
$geo_size_list_output_href->[$_] = hex($1); | |
$geo_count_list_output_href->[$_] = $2; | |
} | |
} | |
} | |
#**************************************************************************** | |
# subroutine: SCHEME Configure Routines :: Query Flash Block Size | |
# input: Flash Offset Address | |
# Output: Flash block size | |
#**************************************************************************** | |
sub config_query_flash_block_sz | |
{ | |
my ($offset, $COMM_MDL_INFO_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL) = @_; | |
&error_handler("pcore\\tools\\emigenflash.pl: Query Block Size at $offset larger than available size!", __FILE__, __LINE__) if ($offset > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
for (0..$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL) | |
{ | |
return ($ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL->[$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL-$_]) if ($offset >= $ENTIRE_BLOCK_INFO_START_LIST_LOCAL->[$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL-$_]); | |
} | |
&error_handler("pcore\\tools\\emigenflash.pl: Unreachable!", __FILE__, __LINE__); | |
} | |
#**************************************************************************** | |
# subroutine: flash_opt_h_file_body | |
# return: flash opt header file | |
#**************************************************************************** | |
sub flash_opt_gen_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $THEMF_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, $entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL) = @_; | |
my $current_nor_opt; | |
##if (($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPSDRAM') and ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPDDR') and ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPDDR2')) | |
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'LPDDR2') | |
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
#{ | |
if ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i) | |
{ | |
$current_nor_opt .= "#define __PAGE_BUFFER_PROGRAM__\n"; | |
} | |
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'SERIAL_FLASH') | |
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$current_nor_opt .= "#define __SERIAL_FLASH__\n"; | |
} | |
### Define flash types | |
my $cnt_sibley = 0; | |
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
if ($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Comm. Series'} =~ /(\w*)/i) | |
{ | |
my $tmp_series = $1; | |
if ($current_nor_opt =~ /$tmp_series/) | |
{ | |
} | |
else | |
{ | |
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'SERIAL_FLASH') | |
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$current_nor_opt .= "#define SF_DAL_" . $tmp_series . "\n"; | |
} | |
else | |
{ | |
$current_nor_opt .= "#define NOR_FLASH_TYPE_" . $tmp_series . "\n"; | |
if ($tmp_series eq 'INTEL_SIBLEY') | |
{ | |
$cnt_sibley++; | |
} | |
} | |
} | |
} | |
} | |
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
if ($cnt_sibley != $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
$current_nor_opt .= "#define __NON_INTEL_SIBLEY__\n"; | |
} | |
$current_nor_opt .= "\n"; | |
$current_nor_opt .= "\n"; | |
if ($COMM_MDL_INFO_LOCAL->{0}->{'Bank'} =~ /M/i) | |
{ | |
$current_nor_opt .= "#define __MULTI_BANK_NOR_DEVICE__\n"; | |
} | |
elsif ($COMM_MDL_INFO_LOCAL->{0}->{'Bank'} =~ /S/i) | |
{ | |
$current_nor_opt .= "#define __SINGLE_BANK_NOR_DEVICE__\n"; | |
} | |
} | |
#} | |
if (($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'FALSE') and ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'FALSE')) | |
{ | |
$current_nor_opt .= "#define __SMART_PHONE_PLATFORM__\n";##for Not Run CkSysDrv.pl, will check FAT valid, but no flash now | |
} | |
### | |
my $pbp_size = ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i) | |
? $COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Size(W)'} | |
: 0; | |
### | |
my $nor_block_size_str = sprintf("0x%X", $nor_block_size); | |
### | |
my $nand_total_size = 0; | |
my $nand_block_size = 0; | |
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
#{ | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
$nand_total_size = ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} == 0xffffffff) | |
? 0 | |
: ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} / (1024*1024)); | |
$nand_block_size = $COMM_MDL_INFO_LOCAL->{0}->{'NAND Block Size(KB)'}; | |
} | |
#} | |
my $base_addr_string = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'}); | |
my $fat_space_string = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'}); | |
### | |
my $fota_check; | |
if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM') | |
{ | |
$fota_check = <<"__TEMPLATE"; | |
#ifndef __FOTA_DM__ | |
#error "$THEMF: Error! FOTA_ENABLE should be set to FOTA_DM!" | |
#endif /* __FOTA_DM__ */ | |
__TEMPLATE | |
} | |
else | |
{ | |
$fota_check = <<"__TEMPLATE"; | |
#ifdef __FOTA_DM__ | |
#error "$THEMF_LOCAL: Error! FOTA_ENABLE should not be defined!" | |
#endif /* __FOTA_DM__ */ | |
__TEMPLATE | |
} | |
### | |
my ($fota_nor_region_def, $fota_nor_block_def, $fota_nor_bank_def); | |
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'NOR_RAM_MCP') | |
{ | |
$fota_nor_region_def = ®ion_info($entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL, undef, '\\'); | |
$fota_nor_block_def = &block_info($entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, '\\'); | |
$fota_nor_bank_def = &bank_info($entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, 0, $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}, '\\'); | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
/* | |
******************************************************************************* | |
PART 1: | |
FLASH CONFIG Options Definition here | |
******************************************************************************* | |
*/ | |
$current_nor_opt | |
/* | |
******************************************************************************* | |
PART 2: | |
FLASH FDM FEATURE CONFIG PARAMETERS translated from Manual custom_Memorydevice.h | |
******************************************************************************* | |
*/ | |
#define BUFFER_PROGRAM_ITERATION_LENGTH ($pbp_size) | |
/* | |
******************************************************************************* | |
PART 3: | |
FLASH GEOMETRY translated from MEMORY DEVICE DATABASE | |
******************************************************************************* | |
*/ | |
/* NOR flash maximum block size (Byte) in file system region */ | |
#define NOR_BLOCK_SIZE $nor_block_size_str | |
/* NAND flash total size (MB). PLEASE configure it as 0 if it is unknown. */ | |
#define NAND_TOTAL_SIZE $nand_total_size | |
/* NAND flash block size (KB). PLEASE configure it as 0 if it is unknown. */ | |
#define NAND_BLOCK_SIZE $nand_block_size | |
/* | |
******************************************************************************* | |
PART 4: | |
FLASH FAT CONFIG translated from Manual custom_Memorydevice.h | |
******************************************************************************* | |
*/ | |
#define NOR_FLASH_BASE_ADDRESS_DEFAULT ($base_addr_string) | |
#define NOR_ALLOCATED_FAT_SPACE_DEFAULT ($fat_space_string) | |
#define FOTA_DM_FS_OFFSET $nfb_fat_size_offset | |
#define FOTA_DM_FS_SECTOR_OFFSET $nfb_partition_sector_offset | |
/* | |
******************************************************************************* | |
PART 6: | |
FOTA UPDATABLE FLASH AREA | |
******************************************************************************* | |
*/ | |
$fota_check | |
#define CONFIG_FOTA_NOR_REGION_DEF \\ | |
$fota_nor_region_def | |
#define CONFIG_FOTA_NOR_BLOCK_DEF \\ | |
$fota_nor_block_def | |
#define CONFIG_FOTA_NOR_BANK_DEF \\ | |
$fota_nor_bank_def | |
__TEMPLATE | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: combo_flash_config_h_file_body | |
# return: | |
#**************************************************************************** | |
sub combo_flash_config_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_; | |
### There should be totally 8 BlockInfo and BankInfo | |
my $MAX_BLOCK_INFO = 8; | |
my $MAX_BANK_INFO = 8; | |
### Fill-in the information of each memory | |
my $combo_mem_info_struct; | |
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
my $comma; | |
my $cmem_fdm_type; | |
my $pbp_size; | |
my $cur_block_str; | |
my @cur_blocks; | |
my $cur_bank_str; | |
my @cur_banks; | |
my $cur_uni_block_str; | |
my $cur_uni_block; | |
my ($block_info_template, $bank_info_template); | |
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
#{ | |
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'NAND_RAM_MCP')##MT6290 MCP | |
{ | |
#todo | |
} | |
else ##MT6290 Discrete DRAM/FLASH | |
{ | |
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
#print "Serial Flash Support!\n"if ($DebugPrint == 1); | |
$comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : ""; | |
$cmem_fdm_type = 'CMEM_FDM_NOR_DEFAULT'; | |
$pbp_size = 0; | |
if ($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'PBP'}->{'Y / N'} =~ /Y/i) | |
{ | |
$pbp_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'PBP'}->{'Size (Byte)'}; | |
} | |
$cur_block_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Block Info.'}; | |
@cur_blocks = &split_info($cur_block_str); # list of Block Info. | |
$cur_bank_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'}; | |
@cur_banks = &split_info($cur_bank_str); # list of Bank Info. | |
$cur_uni_block_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Uniform Block (KB)'}; | |
$cur_uni_block = &split_info_for_UB($cur_uni_block_str); | |
} | |
else #if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE'), No flash or NAND gen dummy file | |
{ | |
#print "NAND Flash Gen Dummy!\n"if ($DebugPrint == 1); | |
#$comma = 0; | |
$comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : ""; | |
$cmem_fdm_type = ''; | |
$pbp_size = 0; | |
$cur_block_str = ''; | |
@cur_blocks = &split_info($cur_block_str); # list of Block Info. | |
$cur_bank_str = ''; | |
@cur_banks = &split_info($cur_bank_str); # list of Bank Info. | |
$cur_uni_block_str = ''; | |
$cur_uni_block = &split_info_for_UB($cur_uni_block_str); | |
} | |
} | |
#} | |
for (0..($MAX_BLOCK_INFO-1)) | |
{ | |
$block_info_template .= " "; | |
if (defined $cur_blocks[$_]) | |
{ | |
$block_info_template .= $cur_blocks[$_]; | |
} | |
else | |
{ | |
$block_info_template .= "EndRegionInfo"; | |
} | |
if ($_ != ($MAX_BLOCK_INFO-1)) | |
{ | |
$block_info_template .= ",\n"; | |
} | |
} | |
for (0..($MAX_BANK_INFO-1)) | |
{ | |
$bank_info_template .= " "; | |
if (defined $cur_banks[$_]) | |
{ | |
$bank_info_template .= $cur_banks[$_]; | |
} | |
else | |
{ | |
$bank_info_template .= "EndBankInfo"; | |
} | |
if ($_ != ($MAX_BANK_INFO-1)) | |
{ | |
$bank_info_template .= ",\n"; | |
} | |
} | |
$combo_mem_info_struct .= <<"__TEMPLATE"; | |
{ // $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'} | |
$cmem_fdm_type, | |
$pbp_size, // Page Buffer Program Size | |
$cur_uni_block, // Unifom Blocks | |
{ // BlockInfo Start | |
$block_info_template | |
}, // BlockInfo End | |
{ // BankInfo Start | |
$bank_info_template | |
} // BankInfo End | |
}$comma | |
__TEMPLATE | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
#define CMEM_MAX_BLOCKS $cmem_max_blocks | |
#define CMEM_MAX_SECTORS $cmem_max_sectors | |
COMBO_MEM_TYPE_MODIFIER COMBO_MEM_TYPE_NAME COMBO_MEM_INST_NAME = { | |
COMBO_MEM_STRUCT_HEAD | |
$combo_mem_info_struct | |
COMBO_MEM_STRUCT_FOOT | |
}; | |
__TEMPLATE | |
} | |
#**************************************************************************** | |
# subroutine: combo_nfi_config_h_file_body | |
# return: | |
#**************************************************************************** | |
sub combo_nfi_config_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_; | |
### Fill-in the information of each memory | |
my $combo_nfi_info_struct; | |
### There should be totally 8 Flash ID entries | |
my $MAX_FLASH_ID = 8; | |
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
$combo_nfi_info_struct .= "/* $_ */\n"; | |
my $vendor = uc($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Vendor'}); | |
#$combo_nfi_info_struct .= " {\n" ." {" . "\"$vendor $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}\"" ."}, // DevName_str (64 bytes)\n";#part time number | |
$combo_nfi_info_struct .= " {\n" ." 0x00000301,\n" ." {" . "\"$vendor $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}\"" ."}, // NFI_Device_Name (64 bytes)\n";#part time number | |
###get flash id string | |
my $flash_id_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Flash ID'}; | |
$flash_id_str =~ s/\{//; # remove parentheses | |
$flash_id_str =~ s/\}//; # remove parentheses | |
$flash_id_str =~ s/\s+//g; # remove spaces | |
### parse the flash id string | |
my $saved_sep = $/; | |
undef $/; | |
my @flash_id = split(/\,/, $flash_id_str); | |
$/ = $saved_sep; | |
my $flash_id_cnt = $#flash_id + 1; | |
my $flash_id_template; | |
my $flash_id_mask; | |
#$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_])) .","; | |
#$flash_id_mask .= "0xFF" .","; | |
for (0..($MAX_FLASH_ID-1)) | |
{ | |
if (defined $flash_id[$_]) | |
{ | |
$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_])); | |
$flash_id_mask .= "0xFF"; | |
} | |
else | |
{ | |
$flash_id_template .= "0xFF"; | |
$flash_id_mask .= "0x00"; | |
} | |
if ($_ != ($MAX_FLASH_ID-1)) | |
{ | |
$flash_id_template .= ", "; | |
$flash_id_mask .= ", "; | |
} | |
} | |
$combo_nfi_info_struct .= " {" .$flash_id_template ."}, // ID_info\n"; | |
$combo_nfi_info_struct .= " {" .$flash_id_mask ."}, // ID_valid_mask\n"; | |
#$combo_nfi_info_struct .= " " .$MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Size(MB)'} .", // deviceSize (MByte)\n"; | |
$combo_nfi_info_struct .= " " .$MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Size(MB)'} .", // NFI_Device_Size (MByte)\n"; | |
#$combo_nfi_info_struct .= " " .sprintf("0x%05x", $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'}*1024) .", // blockSize (byte)\n"; | |
$combo_nfi_info_struct .= " " .sprintf("0x%05x", $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'}*1024) .", // NFI_Block_Size (byte)\n"; | |
###Parsing special info | |
my $nand_flash_key_ref = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{$MAKEFILE_OPTIONS_LOCAL->{'platform'}}; | |
foreach my $nand_flash_key (sort keys %{$nand_flash_key_ref}) | |
{ | |
#print "1-1 $nand_flash_key\n"if ($DebugPrint == 1); | |
if ($nand_flash_key =~ /(\d+)MHz NFIC Config/) | |
{ | |
my $nand_flash_cfg = $nand_flash_key; | |
foreach my $nand_flash_key (sort keys %{$nand_flash_key_ref->{$nand_flash_cfg}}) | |
{ | |
my $val = $nand_flash_key_ref->{$nand_flash_cfg}->{$nand_flash_key}; | |
if (($val ne 'x') && ($val ne 'X') && ($val ne '')) | |
{ | |
$combo_nfi_info_struct .=" " .$val .", // $nand_flash_key" . "\n"; | |
} | |
} | |
} | |
else | |
{ | |
my $val = $nand_flash_key_ref->{$nand_flash_key}; | |
#print "1-2 $val\n"if ($DebugPrint == 1); | |
if (($val ne 'x') && ($val ne 'X') && ($val ne '')) | |
{ | |
$combo_nfi_info_struct .= " " .$val .", // $nand_flash_key" . "\n"; | |
} | |
} | |
} | |
if($_ != $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
$combo_nfi_info_struct .= " },\n"; | |
} | |
else | |
{ | |
$combo_nfi_info_struct .= " }\n"; | |
} | |
__TEMPLATE | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
#define COMBO_NAND_FLASH_NUM $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT} | |
const combo_nand_flash_list_v01 COMBO_NAND_Table[] = | |
{ | |
$combo_nfi_info_struct | |
}; | |
__TEMPLATE | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: combo_flash_id_h_file_body | |
# return: | |
#**************************************************************************** | |
sub combo_flash_id_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_; | |
### There should be totally 8 Flash ID entries | |
my $MAX_FLASH_ID = 8; | |
### Fill-in the information of each memory | |
my $combo_mem_info_struct; | |
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) | |
{ | |
my $comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : ""; | |
my $cmem_type; | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
$cmem_type = "CMEM_TYPE_NAND"; | |
} | |
elsif ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$cmem_type = "CMEM_TYPE_SERIAL_NOR_FLASH"; | |
} | |
else | |
{ | |
print "No flash support!\n"if ($DebugPrint == 1); | |
} | |
###get nand page size | |
my $nand_page_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Page size(B)'}; | |
my $nand_block_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'}; | |
$nand_page_size = $nand_page_size . "," . $nand_block_size; | |
###get flash id string | |
my $flash_id_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Flash ID'}; | |
$flash_id_str =~ s/\{//; # remove parentheses | |
$flash_id_str =~ s/\}//; # remove parentheses | |
$flash_id_str =~ s/\s+//g; # remove spaces | |
### parse the flash id string | |
my $saved_sep = $/; | |
undef $/; | |
my @flash_id = split(/\,/, $flash_id_str); | |
$/ = $saved_sep; | |
my $flash_id_cnt = $#flash_id + 1; | |
my $flash_id_template; | |
for (0..($MAX_FLASH_ID-1)) | |
{ | |
if (defined $flash_id[$_]) | |
{ | |
##$flash_id_template .= $flash_id[$_]; | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
$flash_id_template .= sprintf("0x%04X", hex($flash_id[$_])); | |
#print "$_: $flash_id_template\n"if ($DebugPrint == 1); | |
} | |
elsif($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_])); | |
} | |
} | |
else | |
{ | |
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
$flash_id_template .= "0x0000"; | |
} | |
elsif($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$flash_id_template .= "0x00"; | |
} | |
} | |
if ($_ != ($MAX_FLASH_ID-1)) | |
{ | |
$flash_id_template .= ", "; | |
} | |
} | |
$combo_mem_info_struct .= <<"__TEMPLATE"; | |
{ // $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'} | |
$cmem_type, | |
$flash_id_cnt, // Valid ID length | |
{$flash_id_template} // Flash ID | |
}$comma | |
__TEMPLATE | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
COMBO_MEM_TYPE_MODIFIER COMBO_MEM_TYPE_NAME COMBO_MEM_INST_NAME = { | |
COMBO_MEM_STRUCT_HEAD | |
$combo_mem_info_struct | |
COMBO_MEM_STRUCT_FOOT | |
}; | |
__TEMPLATE | |
} | |
#**************************************************************************** | |
# subroutine: custom_flash_c_file_body | |
# return: | |
#**************************************************************************** | |
sub custom_flash_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $MCP_LIST_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL,$LPSDRAM_CHIP_SELECT_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $nor_size_Mb_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, $fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, $entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL) = @_; | |
my $cs1_base_address = 0; | |
my $flash_limit = 0; | |
my $flash_size = 0; | |
if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
{ | |
my $SPI_Base = 0xA0000000; | |
$cs1_base_address = sprintf("0x%08X", $SPI_Base);#MT6290 Flash Memory Base Address | |
$flash_limit = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
$flash_size = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
#print "MT6290: $cs1_base_address, $flash_limit, $flash_size\n"if ($DebugPrint == 1); | |
if($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE') | |
{ | |
##MT6290 Work aroud for SDS, when in HOSTED/ROUTER Project, NOR_FLASH_SIZE is MD End(96MB), other Projects is Flash Size | |
if((($MAKEFILE_OPTIONS_LOCAL->{'smart_phone_core'} eq 'ANDROID_MODEM') and ($MAKEFILE_OPTIONS_LOCAL->{'ccci_fs_support'} eq 'FALSE')) or (($MAKEFILE_OPTIONS_LOCAL->{'modem_card'} eq 'FULL') and ($MAKEFILE_OPTIONS_LOCAL->{'smart_phone_core'} eq 'MODEM_HOST'))) | |
#if($MAKEFILE_OPTIONS_LOCAL->{'modem_card'} eq 'FULL') | |
{ | |
my $MDFlashEnd = 96*1024*1024; | |
$flash_size = sprintf("0x%08X", $MDFlashEnd); | |
} | |
} | |
} | |
### | |
my $pbp_size = ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i) | |
? $COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Size(W)'} | |
: 0; | |
### | |
my $bank_info_string = &bank_info( $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL ); | |
### | |
my $sub_content_block1 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'REGION_INFO_LAYOUT'); | |
my $sub_content_block2 = &block_info($entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL); | |
my $sub_content_block3; | |
my $sub_content_block4; | |
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
#{ | |
my $ori_bank_info = &bank_info($entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, 0, $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); | |
### ? what is the purpose? | |
$sub_content_block3 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'oriRegionInfo'); | |
$sub_content_block4 .= <<"__TEMPLATE"; | |
static NORBankInfo oriBankInfo[] = | |
{ | |
$ori_bank_info | |
EndBankInfo | |
}; | |
__TEMPLATE | |
chomp $sub_content_block4; | |
#} | |
### | |
my $region_info_disk0 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK0_REGION_INFO_LAYOUT'); | |
my $region_info_disk1 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK1_REGION_INFO_LAYOUT'); | |
my $region_info_entire = ®ion_info($entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL, 'ENTIRE_DISK_REGION_INFO_LAYOUT'); | |
### | |
my $template1; | |
$template1 .= <<"__TEMPLATE__"; | |
/******************************************************************************* | |
NOTICE: Fill the flash region information table, a region is the memory space | |
that contains continuous sectors of equal size. Each region element | |
in the table is the format as below: | |
{S_sector, N_sector}, | |
S_sector: the size of sector in the region | |
N_sector: the number of sectors in the region | |
*******************************************************************************/ | |
$sub_content_block1 | |
$region_info_disk0 | |
$region_info_disk1 | |
$region_info_entire | |
/******************************************************************************* | |
NOTICE. Modify the value of TOTAL_BLOCKS, which is the sum of the number of | |
sectors in all regions. | |
Note : The Maximum value of TOTAL_BLOCKS is (127). | |
*******************************************************************************/ | |
#define TOTAL_BLOCKS $cmem_max_blocks | |
/******************************************************************************* | |
NOTICE. Modify the value of page buffer size in WORD for page buffer program | |
*******************************************************************************/ | |
//kal_uint32 PAGE_BUFFER_SIZE = $pbp_size; | |
#define BANK_INFO_LAYOUT $bank_info_string | |
/******************************************************************************* | |
NOTICE. NOR FLASH BLOCKS SIZE LOOKUP TABLE | |
Each entry element | |
{Offset, Block_Size}, | |
Offset: the offset address | |
Block_Size: the size of block | |
*******************************************************************************/ | |
$sub_content_block2 | |
__TEMPLATE__ | |
### | |
my $flash_id_str; | |
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6290') | |
#{ | |
#print "Flash ID: $MDL_INFO_LIST_LOCAL->[1]->{1}->{'Flash ID'}!\n"if ($DebugPrint == 1); | |
$flash_id_str .= <<"__TEMPLATE__"; | |
const kal_char FLASH_ID[] = "$MDL_INFO_LIST_LOCAL->[1]->{1}->{'Flash ID'}"; | |
__TEMPLATE__ | |
#} | |
chomp $flash_id_str; | |
### | |
my ($cs0_info, $cs1_info); | |
my ($pn0_str, $pn1_str); | |
if ((!defined $MAKEFILE_OPTIONS_LOCAL->{'combo_memory_support'}) or ($MAKEFILE_OPTIONS_LOCAL->{'combo_memory_support'} eq 'FALSE')) | |
{ | |
if (defined $MCP_LIST_LOCAL->[1]->{0}) | |
{ | |
$cs0_info .= <<"__TEMPLATE__"; | |
* CS0_PART_NUMBER: $MCP_LIST_LOCAL->[1]->{0} | |
__TEMPLATE__ | |
chomp $cs0_info; | |
$pn0_str .= <<"__TEMPLATE__"; | |
const kal_char PART_NUMBER_0[] = "$MCP_LIST_LOCAL->[1]->{0}"; | |
__TEMPLATE__ | |
chomp $pn0_str; | |
} | |
if (defined $MCP_LIST_LOCAL->[1]->{1}) | |
{ | |
$cs1_info .= <<"__TEMPLATE__"; | |
* CS1_PART_NUMBER: $MCP_LIST_LOCAL->[1]->{1} | |
__TEMPLATE__ | |
chomp $cs1_info; | |
$pn1_str .= <<"__TEMPLATE__"; | |
const kal_char PART_NUMBER_1[] = "$MCP_LIST_LOCAL->[1]->{1}"; | |
__TEMPLATE__ | |
chomp $pn1_str; | |
} | |
} | |
### | |
my $flash_density; | |
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE') | |
{ | |
$flash_density .= <<"__TEMPLATE__"; | |
* NOR_FLASH_DENSITY: $flash_limit | |
* NOR_FLASH_SIZE(Mb): $nor_size_Mb_LOCAL | |
__TEMPLATE__ | |
chomp $flash_density; | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
#define NOR_FLASH_BASE_ADDR $cs1_base_address | |
/* | |
#ifdef REMAPPING | |
#define NOR_FLASH_BASE_ADDR $cs1_base_address | |
#define RAM_BASE_ADDR 0x00000000 | |
#else | |
#define NOR_FLASH_BASE_ADDR 0x00000000 | |
#define RAM_BASE_ADDR $cs1_base_address | |
#endif | |
*/ | |
/* | |
**************************************************************************** | |
PART 2: | |
Essential Information of NOR Flash Geometry Layout Information | |
**************************************************************************** | |
*/ | |
$template1 | |
#define NOR_FLASH_SIZE $flash_size | |
$flash_id_str | |
/**************************************************** | |
* This part is for auto-gen validity CHECK * | |
* Don't modify any content in this comment section * | |
$cs0_info | |
$cs1_info | |
$flash_density | |
$sub_content_block3 | |
$sub_content_block4 | |
****************************************************/ | |
__TEMPLATE | |
} | |
#**************************************************************************** | |
# subroutine: custom_flash_norfdm5_c_file_body | |
# return: | |
#**************************************************************************** | |
sub custom_flash_norfdm5_h_file_body | |
{ | |
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL) = @_; | |
my $bank_info_string = &bank_info( $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL ); | |
### | |
my $nor_total_lsmt = 1; | |
my $count = 0; | |
my $sum = 1; | |
my $tmp_regions_sum = $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL; | |
if ($MEM_DEV_LIST_INFO{0}->{'Comm. Series'} eq 'INTEL_SIBLEY') | |
{ | |
if ($tmp_regions_sum > (64*1024*1024)) | |
{ | |
my $count = 0; | |
my $sum = 1; | |
$tmp_regions_sum /= 1024; | |
while ($sum < $tmp_regions_sum) | |
{ | |
$sum *= 2; | |
$count++; | |
} | |
$count -= 8; | |
for (my $i=0; $i<$count; $i++) | |
{ | |
$nor_total_lsmt *= 2; | |
} | |
} | |
else | |
{ | |
my $count = 0; | |
my $sum = 1; | |
$tmp_regions_sum /= 1024; | |
while ($sum < $tmp_regions_sum) | |
{ | |
$sum *= 2; | |
$count++; | |
} | |
if (($count/2) == 1) | |
{ | |
$count += 1; | |
} | |
$count /= 2; | |
for (my $i=0; $i<$count; $i++) | |
{ | |
$nor_total_lsmt *= 2; | |
} | |
} | |
} | |
else | |
{ | |
if ($tmp_regions_sum > (32*1024*1024)) | |
{ | |
my $count = 0; | |
my $sum = 1; | |
$tmp_regions_sum /= 512; | |
while ($sum < $tmp_regions_sum) | |
{ | |
$sum *= 2; | |
$count++; | |
} | |
$count -= 8; | |
for (my $i=0; $i<$count; $i++) | |
{ | |
$nor_total_lsmt *= 2; | |
} | |
} | |
else | |
{ | |
my $count = 0; | |
my $sum = 1; | |
$tmp_regions_sum /= 512; | |
while ($sum < $tmp_regions_sum) | |
{ | |
$sum *= 2; | |
$count++; | |
} | |
if (($count/2) == 1) | |
{ | |
$count += 1; | |
} | |
$count /= 2; | |
for (my $i=0; $i<$count; $i++) | |
{ | |
$nor_total_lsmt *= 2; | |
} | |
} | |
} | |
### | |
my $template = <<"__TEMPLATE"; | |
#ifdef __NOR_FDM5__ | |
/******************************************************************************* | |
Follow the 4 steps below to configure flash memory | |
Step 1. Fill the flash bank (partition) information table, | |
flash device features flexible, multi-bank read-while-program and | |
read-while-erase capability, enabling background programming or erasing in | |
one bank simultaneously with code execution or data reads in another bank. | |
Each element in the table is the format as below: | |
{bank size, bank number}, | |
Step 2. Modify the value of LSMT, you can see MemoryDevice_FlashDisk_FAQ for | |
detail information | |
Step 2. Define the toal sectors (512bytes) of system drive | |
the remainder is the size of public drive | |
If there is no partiton (just one drive, system drive) | |
set this value to STORAGE_NO_PARTITION (0xFFFFFFFF) | |
Note : Code region and FAT region can not share the same bank (partition) | |
*******************************************************************************/ | |
/*********** | |
* Step 1. * | |
***********/ | |
#define NOR_FDM5_BANK_INFO_LAYOUT $bank_info_string | |
/*********** | |
* Step 2. * | |
***********/ | |
#define NOR_TOTAL_LSMT $nor_total_lsmt | |
/*********** | |
* Step 3. * | |
***********/ | |
// Set NOR_SYSDRV_SECTORS to 0 will disable this setting and use PARTITION_SECTORS in custom_memorydevice.h to set user drive size. | |
#define NOR_SYSDRV_SECTORS 0 | |
#endif //__NOR_FDM5__ | |
__TEMPLATE | |
return $template; | |
} | |
#**************************************************************************** | |
# subroutine: split_info_for_UB | |
# return: List of RegionInfo/BlockInfo/BankInfo | |
# input: $info: Excel value to be split | |
#**************************************************************************** | |
sub split_info_for_UB | |
{ | |
my $text = shift; | |
my @new = (); | |
my $ref_str; | |
my $i; | |
push(@new, $+) while $text =~ m{ | |
"([^\"\\]*(?:\\.[^\"\\]*)*)", ? | |
| ([^,]+), ? | |
| , | |
}gx; | |
push(@new, undef) if substr($text, -1,1) eq ','; | |
for($i = 0; $i < @new; $i++){ | |
print "$i: $new[$i]\n"; | |
} | |
$ref_str = "("; | |
for($i = 0; $i < @new; $i++){ | |
if($i == (@new -1)) | |
{ | |
$ref_str .= $new[$i]; | |
} | |
else | |
{ | |
$ref_str .= $new[$i] . "|"; | |
} | |
} | |
$ref_str .= ")"; | |
print "$ref_str\n"; | |
return $ref_str; | |
} | |
return 1; |