powershell-flash.psm1

# 打印详情日志
function LOG_INF {
    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $msg
    )
    BEGIN
    {
        Write-Host ("[info] "+"===> "+$msg) -ForegroundColor Green
    }
}

# 打印warn
function LOG_WARN {
    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $msg
    )
    BEGIN
    {
        Write-Host ("[warn] "+"===> "+$msg) -ForegroundColor Yellow
    }
}

# 打印error
function LOG_ERR {
    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $msg
    )
    BEGIN
    {
        Write-Host ("[error] "+"===> "+$msg) -ForegroundColor Red
    }
}

$efm_device = "EFM32PG12B500F1024"

function efm_flash_hex {
    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $app_repath_hex
    )
    BEGIN
    {
        LOG_INF "擦除芯片..."
        & commander device -d $efm_device masserase | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "擦除芯片失败!"
            return -1
        }

        LOG_INF "烧录hex..."
        & commander flash -d $efm_device $app_repath_hex | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "烧录hex失败!"
            return -1
        }

        LOG_INF "设备重启"
        & commander device -d $efm_device reset | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "设备重启失败!"
            return -1
        }
        LOG_INF "============== HEX 烧写成功!=============="
        return 0
    }

}

function efm_flash_bin {
    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $app_repath_bin,
        [parameter(Mandatory = $true,Position=1)]
        [string] $boot,
        [parameter(Mandatory = $true,Position=2)]
        [long] $address,
        [parameter(Mandatory = $true,Position=3)]
        [switch] $earse_all
    )
    BEGIN
    {
        $address_hex = "0x"+("{0:X0}" -f $address)
        $boot_filepath = (Resolve-Path $boot).ToString()
        if(-not (Test-Path $app_filepath)){
            LOG_ERR ($boot + " is not found!")
            return -1
        }
        $boot_file_suffix = ($boot_filepath.split(".")[1])
        if(-not ($boot_file_suffix -eq "hex")){
            LOG_ERR ($boot + " is type error!")
            return -1
        }

        $config_path = (Join-Path ($PSScriptRoot) config\efm32)
        $config_ota_state_file = (Join-Path $config_path ota_state.bin)
        $config_disable_bootloader_file = (Join-Path $config_path disable_bootloader.hex)
        if($earse_all){
            LOG_INF "擦除芯片..."
            & commander device -d $efm_device masserase | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "擦除芯片失败!"
                return -1
            }
        }else{
            LOG_INF "擦除SWAP..."
            & commander device -d $efm_device pageerase --range 0x7c800:+0x77800 | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "擦除SWAP失败!"
                return -1
            }
        }

        if(-not $earse_all){
            LOG_INF "擦除OTA state..."
            LOG_INF ("commander flash -d "+ $efm_device + "--address 0xFE80C "+$config_ota_state_file)
            & commander flash -d $efm_device --address 0xFE80C $config_ota_state_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "擦除OTA state失败!"
                return -1
            }
        }

        LOG_INF "烧写Disable Bootloader..."
        & commander flash -d $efm_device $config_disable_bootloader_file | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "烧写Disable Bootloader失败!"
            return -1
        }

        LOG_INF "烧写BOOT..."
        & commander flash -d $efm_device $boot_filepath | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "烧写BOOT失败!"
            return -1
        }

        LOG_INF "烧写APP..."
        & commander flash -d $efm_device --address $address_hex $app_repath_bin | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "烧写APP失败!"
            return -1
        }

        LOG_INF "设备重启"
        & commander device -d $efm_device reset | Write-Information -InformationAction Continue
        if(-not ($?)){
            LOG_ERR "设备重启失败!"
            return -1
        }
        LOG_INF "============== BIN 烧写成功!=============="
        return 0
    }
}

# EFM的下载,通过commander工具下载
function efm_flash {
    <#
    .SYNOPSIS
        Silabs EFM series chip firmware download.
 
    .DESCRIPTION
        Use this function to download hex or bin to the Silabs EFM chip.
 
    .PARAMETER app_filename
        Download the hex or bin file for the application. [string]
 
    .PARAMETER boot_filename_hex
        Download the HEX file for bootload,which is only valid when applying the bin file. [string]
 
    .PARAMETER address
        The address to download the application bin file is valid only when the application is running the bin file. [long]
 
    .PARAMETER earse_all
        Whether to erase the application bin file when downloading it
 
    .EXAMPLE
        Get-MrAutoStoppedService -ComputerName 'Server1', 'Server2'
 
    .EXAMPLE
        efm_flash xxx.hex
 
    .EXAMPLE
        efm_flash xxx.bin boot.hex 0x5000
 
    .EXAMPLE
        efm_flash xxx.bin boot.hex 0x5000 -earse_all
 
    .NOTES
        Author: Wang Yan
    #>

    param (
        [parameter(Mandatory = $true,Position=0)]
        [string] $app_filename,
        [parameter(Position=1)]
        [string] $boot_filename_hex="bootloader.hex",
        [parameter(Position=2)]
        [long] $address = 0x7000,
        [parameter(Position=3)]
        [switch] $earse_all = $false
    )
    BEGIN
    {
        $output = 0
        $app_filepath = (Resolve-Path $app_filename).ToString()
        if(-not (Test-Path $app_filepath)){
            LOG_ERR ($app_filename + " is not found!")
            return -1
        }
        $app_file_suffix = ($app_filepath.split(".")[1])

        if($app_file_suffix -eq "bin"){
            $output = efm_flash_bin -app_repath_bin $app_filepath -boot $boot_filename_hex -address $address -earse_all:$earse_all
            if ($output -eq 0){
                LOG_INF ($app_filepath+" 下载成功...")
            }
        }elseif ($app_file_suffix -eq "hex") {
            $output = efm_flash_hex $app_filepath
            if ($output -eq 0){
                LOG_INF ($app_filepath+ " 下载成功....")
            }
        }else{
            LOG_ERR ($app_filename+ " 的文件类型错误!")
        }
    }
}

function efm_select_factory {
    <#
    .SYNOPSIS
        Silabs EFM series chip select factory step.
 
    .DESCRIPTION
        Through this function to carry out the selection of factory test steps.
 
    .EXAMPLE
        efm_select_factory
 
    .INPUTS
        String
 
    .NOTES
        Author: Wang Yan
    #>


    $input_msg = (
        [PSCustomObject] @{"选择编号"="1";"描述"="厂测一"},
        [PSCustomObject] @{"选择编号"="2";"描述"="厂测一USB供电"},
        [PSCustomObject] @{"选择编号"="3";"描述"="老化"},
        [PSCustomObject] @{"选择编号"="4";"描述"="厂测二"},
        [PSCustomObject] @{"选择编号"="5";"描述"="厂测二USB供电"},
        [PSCustomObject] @{"选择编号"="6";"描述"="厂测三"},
        [PSCustomObject] @{"选择编号"="7";"描述"="厂测完成"}
    )

    $config_path = (Join-Path ($PSScriptRoot) config\efm32)

    $input_msg | Format-Table | Out-String |Write-Information -InformationAction Continue

    $number = Read-Host "请输入选择编号:"
    $factory_file = ""
    switch ($number) {
        "1" {
            $factory_file = (Join-Path $config_path factory_step1_init.hex)
            LOG_INF "烧写厂测一初始化..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测一初始化失败!"
                return
            }
        }
        "2" {
            $factory_file = (Join-Path $config_path factory_step1_usb_power_on.hex)
            LOG_INF "烧写厂测一USB供电..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测一USB供电失败!"
                return
            }
        }
        "3" {
            $factory_file = (Join-Path $config_path factory_aging.hex)
            LOG_INF "烧写老化测试..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写老化测试失败!"
                return
            }
        }
        "4" {
            $factory_file = (Join-Path $config_path factory_step2_init.hex)
            LOG_INF "烧写厂测二初始化..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测二初始化失败!"
                return
            }
        }
        "5" {
            $factory_file = (Join-Path $config_path factory_step2_usb_power_on.hex)
            LOG_INF "烧写厂测二USB供电..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测二USB供电失败!"
                return
            }
        }
        "6" {
            $factory_file = (Join-Path $config_path factory_step3_init.hex)
            LOG_INF "烧写厂测三初始化..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测三初始化失败!"
                return
            }
        }
        "7" {
            $factory_file = (Join-Path $config_path factory_finish.hex)
            LOG_INF "烧写厂测结束..."
            & commander flash -d $efm_device $factory_file | Write-Information -InformationAction Continue
            if(-not ($?)){
                LOG_ERR "烧写厂测结束失败!"
                return
            }
        }
        Default {
            LOG_ERR "请输入正确编号"
            return
        }
    }

    LOG_INF "设备重启"
    & commander device -d $efm_device reset | Write-Information -InformationAction Continue
    if(-not ($?)){
        LOG_ERR "设备重启失败!"
        return
    }

    LOG_INF "============== 厂测选择成功!=============="
}

function efm_unlock {
    <#
    .SYNOPSIS
        Silabs EFM series chip unlock.
 
    .DESCRIPTION
        Use this function to unlock the chip.
 
    .EXAMPLE
        efm_unlock
 
    .NOTES
        Author: Wang Yan
    #>

    LOG_INF "调试口检查解锁..."
    & commander device lock --debug disable --device $efm_device | Write-Information -InformationAction Continue
    if(-not ($?)){
        LOG_ERR "调试口检查解锁失败!"
        return
    }
    LOG_INF "设备重启"
    & commander device -d $efm_device reset | Write-Information -InformationAction Continue
    if(-not ($?)){
        LOG_ERR "设备重启失败!"
        return
    }
    LOG_INF "============== 设备解锁中,需要重新上电!=============="
    LOG_INF "============== 请重启设备后按任意键盘继续 ==========="
    Read-Host
    LOG_INF "============== 设备解锁成功 ==========="
}

function efm_erase_all {
    <#
    .SYNOPSIS
        Silabs EFM series chip erase all.
 
    .DESCRIPTION
        Chip erasure is performed by this function.
 
    .EXAMPLE
        efm_erase_all
 
    .NOTES
        Author: Wang Yan
    #>

    LOG_INF "擦除芯片..."
    & commander device -d $efm_device masserase | Write-Information -InformationAction Continue
    if(-not ($?)){
        LOG_ERR "擦除芯片失败!"
        return
    }
    LOG_INF "设备重启"
    & commander device -d $efm_device reset | Write-Information -InformationAction Continue
    if(-not ($?)){
        LOG_ERR "设备重启失败!"
        return
    }
    LOG_INF "============== 设备擦除成功!=============="
}

# 导出函数
Export-ModuleMember -Function efm_flash,efm_select_factory,efm_unlock,efm_erase_all