@libs-scripts-mep/grav-fw-pvi
Version:
Auxilia na gravação de microcontroladores por linha de comando através do PVI
444 lines (329 loc) • 18.8 kB
JavaScript
import FWLink from "../daq-fwlink/FWLink.js"
import Log from "../script-loader/utils-script.js"
export default class GravaFW {
static progress
/**
*
* @param {String} dirFirm
* @param {String} dirOpt
* @param {Object} objArguments
* @param {Number} [timeOut=5000]
* @returns
*
* # Exemplos
*
* ```js
* const programPath = "I:/script_repo/fw_repo/fw_v1_0.2.hex"
* const optionPath = "I:/script_repo/fw_repo/opt.hex"
* const writeFirmware = await GravaFW.STM8(programPath, optionPath, { Device: "STM8S003F3" })
* ```
*
* # Retorno
*
* ```js
* { success: Boolean, msg: String }
* ```
*/
static async STM8(dirFirm = null, dirOpt = null, objArguments = {}, timeOut = 5000) {
return new Promise(async (resolve) => {
let validationMsg = ``
if (dirFirm != null && dirOpt != null) { validationMsg = `Verify OPTION BYTE succeeds` }
else if (dirFirm != null) { validationMsg = `Verifying PROGRAM MEMORY succeeds` }
else if (dirOpt != null) { validationMsg = `Verify OPTION BYTE succeeds` }
else { validationMsg = "error" }
let ObjWriteSTM8 = await defineWriteSTM8(dirFirm, dirOpt, objArguments)
let logGravacao = ""
if (ObjWriteSTM8.success) {
const id = FWLink.PVIEventObserver.add((msg, param) => {
console.log(`%cLog Program: ${param[0]}`, ' color: #B0E0E6')
logGravacao = logGravacao + param[0]
this.progress = param[0]
if (param[0] != undefined) {
if (param[0].includes(validationMsg)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: true, msg: "Gravação bem sucedida", dirFirm: dirFirm })
} else if (param[0].includes(`ERROR : Cannot communicate with the tool`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: null, msg: `Gravador não respondeu`, dirFirm: dirFirm })
} else if (param[0].includes(`(API) ERROR`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: null, msg: `Não foi possível realizar a gravação`, dirFirm: dirFirm })
}
}
}, "sniffer.exec")
let timeOutGravacao = setTimeout(() => {
console.log(`%cLog Program:\n\n${logGravacao}`, ' color: #EE0033')
FWLink.PVIEventObserver.remove(id)
resolve({ success: false, msg: `Falha na gravação do firmware final` })
}, timeOut)
} else {
console.log(`%cNenhum diretório de firmware ou option byte informado`, ' color: #EE0033')
resolve({ success: false, msg: `Nenhum diretório de firmware ou option byte informado` })
}
FWLink.runInstructionS("EXEC", [`I:/Teste_Producao/Resources/stvp/STVP_CmdLine.exe`, ObjWriteSTM8.commandLineArguments, "true", "true"])
})
/**
*
* @param {String} dirFirm
* @param {String} dirOpt
* @param {Object} objArguments
* @returns
*/
async function defineWriteSTM8(dirFirm, dirOpt, objArguments) {
return new Promise(async (resolve) => {
const log = objArguments.log == true ? "-log " : ""
const loop = objArguments.loop == true ? "-loop " : "-no_loop "
const erase = objArguments.erase == true ? "-erase " : ""
const blank = objArguments.blank == true ? "-blank " : ""
const verif = objArguments.verif == true ? "-verif " : ""
const verbose = objArguments.verbose == true ? "-verbose " : ""
const version = objArguments.version == true ? "-version " : ""
const progress = objArguments.progress == true ? "-progress " : ""
const readProg = objArguments.readProg == true ? "-readProg " : ""
const readData = objArguments.readData == true ? "-readData " : ""
const readOption = objArguments.readOption == true ? "-readOption " : ""
const no_progProg = objArguments.no_progProg == true ? "-no_progProg " : ""
const warn_protect = objArguments.warn_protect == true ? "-warn_protect " : "-no_warn_protect "
const no_progOption = objArguments.no_progOption == true ? "-no_progOption " : ""
const Port = objArguments.Port != undefined ? `-Port=${objArguments.Port} ` : "-Port=USB "
const ProgMode = objArguments.ProgMode != undefined ? `-ProgMode=${objArguments.ProgMode} ` : "-ProgMode=SWIM "
const Device = objArguments.Device != undefined ? `-Device=${objArguments.Device}` : ""
const NbTools = objArguments.NbTools != undefined ? `-NbTools=${objArguments.NbTools} ` : "-NbTools=1 "
const Tool_ID = objArguments.Tool_ID != undefined ? `-Tool_ID=${objArguments.Tool_ID} ` : "-Tool_ID=0 "
const BoardName = objArguments.BoardName != undefined ? `-BoardName=${objArguments.BoardName} ` : "-BoardName=ST-LINK "
const FileData = objArguments.FileData != undefined ? `-FileOption=${objArguments.FileData} ` : ""
const FileProg = dirFirm != null ? `-FileProg=${dirFirm.replace(/[\\]/g, `\/`).replace(/\.stp|\.STP/, `.HEX`)} ` : ""
const FileOption = dirOpt != null ? `-FileOption=${dirOpt.replace(/[\\]/g, `\/`).replace(/\.stp|\.STP/, `.HEX`)} ` : ""
resolve({
success: true,
commandLineArguments: `${BoardName}${Tool_ID}${NbTools}${Port}${ProgMode}${verbose}` +
`${loop}${warn_protect}${erase}${blank}${verif}${FileProg}${FileOption}${FileData}` +
`${readProg}${readData}${readOption}${log}${progress}${no_progOption}${no_progProg}${version}${version}${Device}`,
})
})
}
}
/**
*
* @param {String} dirProject
* @param {Number} [timeOut=5000]
* @returns
*
* # Exemplos
*
* ```js
* const programPath = "I:/script_repo/fw_repo/fw_v1_0.2.rpj"
* const writeFirmware = await GravaFW.Renesas(programPath)
* ```
*
* # Retorno
*
* ```js
* { success: Boolean, msg: String }
* ```
*/
static async Renesas(dirProject = null, timeOut = 5000) {
return new Promise((resolve) => {
if (dirProject != null) {
let logGravacao = ""
const id = FWLink.PVIEventObserver.add((msg, param) => {
console.log(`%cLog Program: ${param[0]}`, ' color: #B0E0E6')
logGravacao = logGravacao + param[0]
this.progress = param[0]
if (param[0] != undefined) {
if (param[0].includes(`Operation completed.`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: true, msg: "Gravação bem sucedida", dirProject: dirProject })
} else if (param[0].includes(`Cannot find the specified tool.`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: false, msg: `Gravador não respondeu`, dirProject: dirProject })
} else if (param[0].includes(`Error: No project file specifed.`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: false, msg: `Projeto informado é inválido`, dirProject: dirProject })
} else if (param[0].includes(`A framing error occurred while receiving data`)) {
FWLink.PVIEventObserver.remove(id)
clearTimeout(timeOutGravacao)
resolve({ success: false, msg: `Falha ao receber dados do microcontrolador`, dirProject: dirProject })
}
}
}, "sniffer.exec")
FWLink.runInstructionS("EXEC", [`I:/Teste_Producao/Resources/Renesas/RFPV3.Console.exe`, dirProject, "true", "true"])
let timeOutGravacao = setTimeout(() => {
FWLink.PVIEventObserver.remove(id)
resolve({ success: false, msg: `Tempo de gravação excedido` })
}, timeOut)
} else {
resolve({ success: false, msg: `Caminho do firmware não informado` })
}
})
}
/**
* Realiza gravacao nos microcontroladores Nuvoton atraves do PVI, via JLink command line.
*
* @param {string} dirProject caminho do firmware
* @param {string} nameFile nome para o arquivo de comandos JLink que ficará na pasta 'C:/Temp/', sujestão: código effective
* @param {string} device modelo do micrcontrolador
* @param {number} [speed=4000] velocidade de gravação
* @param {number} [timeOut=5000] tempo máximo de gravação
* @returns {Promise<{success: boolean, msg: string}>} - resultado da gravação
*
* # Exemplos
*
* ```js
* const programPath = "I:/script_repo/fw_repo/fw_v1_0.2.hex"
* const codigo_effective = "1234"
* const device = "STM32C031K6"
* const writeFirmware = await GravaFW.JLink_v7(programPath, codigo_effective, device)
* ```
*
* # Retorno
*
* ```js
* { success: Boolean, msg: String }
* ```
*/
static async JLink_v7(dirProject = null, nameFile, device, speed = 4000, timeOut = 5000) {
return new Promise((resolve) => {
FWLink.runInstructionS("JLINK7.init", []) // Inicializa o JLink
let logGravacao = ""
const id = FWLink.PVIEventObserver.add((msg, param) => {
console.log(`%cLog Program: ${param[0]}`, ' color: #B0E0E6')
logGravacao = logGravacao + param[0]
this.progress = param[0]
if (param == "Script processing completed.") {
FWLink.PVIEventObserver.remove(id)
if (logGravacao.includes('Program & Verify speed')) {
clearTimeout(timeOutGravacao)
resolve({ success: true, msg: dirProject })
} else if (logGravacao.includes(`Cannot connect to target.`)) {
clearTimeout(timeOutGravacao)
resolve({ success: false, msg: `Cannot connect to target.` })
}
}
}, "sniffer.exec")
const commandFile = commandJlink(nameFile, speed, dirProject)
FWLink.runInstructionS("EXEC", [`I:/Teste_Producao/Resources/JLink7/JLink.exe`, `-device ${device} -CommandFile ${commandFile}`, "true", "true"])
let timeOutGravacao = setTimeout(() => {
FWLink.PVIEventObserver.remove(id)
resolve({ success: false, msg: `Falha na gravação, verifique a conexão USB do gravador.` })
}, timeOut)
})
function commandJlink(nameFile, speed, dirProject) {
if (FWLink.runInstructionS("vfs.directoryexists", [`C:/Temp/`]) == '1') {
if (FWLink.runInstructionS("vfs.fileexists", [`C:/Temp/${nameFile}.txt`]) == '1') {
FWLink.runInstructionS("EXEC", ["cmd.exe", `/c (echo si 1 & echo speed ${speed} & echo r & echo h & echo erase & echo loadfile ${dirProject} & echo exit) > C:/Temp/${nameFile}.txt`, true, true])
return `C:/Temp/${nameFile}.txt`
} else {
FWLink.runInstructionS("EXEC", ["cmd.exe", `/c (echo texto invalido) > C:/Temp/${nameFile}.txt`, true, true])
return commandJlink(nameFile, speed, dirProject)
}
} else {
FWLink.runInstructionS("vfs.createdirectory", [`C:/Temp/`])
return commandJlink(nameFile, speed, dirProject)
}
}
}
/**
* Realiza gravacao nos microcontroladores Nuvoton atraves do PVI, via JLink command line
* @param {string} sessionStorageTag tag para armazenar e acessar o numero da porta COM
* @param {string} appPath formato esperado: "I:\\Documentos\\Softwares\\ESP32\\INV-161\\31L\\INV-161_INV-161_HW2-31-FW-v1.bat" ou "I:\\Documentos\\Softwares\\ESP32\\INV-161\\31L\\INV-161_INV-161_HW2-31-FW-v1.bin"
* @param {boolean} isBatFile distingue extensão entre .bat e .bin
* @param {number} betweenMsgTimeout timeout maximo para inatividade na comunicação com o ESP32
*
* # Exemplos
*
* ```js
* const AddressFilePath = "I:/firmware/path/FW-v1.bin"
* const result = await GravaFW.ESP32("Controlador", AddressFilePath, false, 5000)
* ```
*
* # Result
*
* ```js
* { success: Boolean, msg: String }
* ```
*/
static async ESP32(sessionStorageTag, AddressFilePath, isBatFile, betweenMsgTimeout = 10000, chip = "esp32") {
return new Promise(async (resolve) => {
await this.checkDependenciesPython()
if (!AddressFilePath) {
resolve({ success: false, msg: "Caminho de arquivo para gravação não especificado", AddressFilePath: AddressFilePath }); return
}
let portsFound = null, tryingPorts = [], lastTimeMsg = new Date().getTime()
const betweenMsgMonitor = setInterval(() => {
if (new Date().getTime() - lastTimeMsg > betweenMsgTimeout) {
clearInterval(betweenMsgMonitor)
FWLink.PVIEventObserver.remove(id)
resolve({ success: false, msg: "esptool.py encontrou um problema e teve que ser finalizado.", AddressFilePath: AddressFilePath }); return
}
}, 1000)
const id = FWLink.PVIEventObserver.add((msg, param) => {
const info = param[0]
lastTimeMsg = new Date().getTime()
console.log(`%cLog Program: ${param}`, ' color: #87CEEB')
if (info.includes("Found")) {
const splittedInfo = info.split(" ")
portsFound = parseInt(splittedInfo[1])
} else if (info.includes("Serial port")) {
const splittedInfo = info.split(" ")
tryingPorts.push(splittedInfo[2])
} else if (info.includes("Failed to connect")) {
if (tryingPorts.length >= portsFound) {
FWLink.PVIEventObserver.remove(id)
resolve({ success: false, msg: "Gravador não conseguiu se conectar com o ESP32", AddressFilePath: AddressFilePath }); return
}
} else if (info.includes("%")) {
this.progress = info
} else if (info.includes("Hard resetting via RTS pin...")) {
sessionStorage.getItem(sessionStorageTag) == null ? sessionStorage.setItem(sessionStorageTag, tryingPorts.pop()) : null
FWLink.PVIEventObserver.remove(id)
resolve({ success: true, msg: "Gravação bem sucedida", AddressFilePath: AddressFilePath })
console.timeEnd("WriteFirmware")
}
}, "PVI.Sniffer.sniffer.exec_return.data")
console.log("writeFirmware ID", id)
let port = ""
sessionStorage.getItem(sessionStorageTag) != null ? port = `-p${sessionStorage.getItem(sessionStorageTag)}` : null
const args = `${port} -b 480600 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m ${AddressFilePath}`
if (isBatFile) {
console.log(`Executando batch: ${AddressFilePath} args: ${port}`)
FWLink.runInstructionS("EXEC", [AddressFilePath, port, "true", "true", "true"])
} else {
console.log(`Executando esptoll, args: ${args}`)
FWLink.runInstructionS("EXEC", ["esptool", args, "true", "true", "true"])
}
})
}
static getScriptPath() {
const pathC = location.pathname.slice(location.pathname.indexOf("C:/"), location.pathname.lastIndexOf("/"))
const pathI = location.pathname.slice(location.pathname.indexOf("I:/"), location.pathname.lastIndexOf("/"))
if (pathC.length > 0) {
return pathC
} else if (pathI.length > 0) {
return pathI
}
}
static async checkDependenciesPython(pyFilePath = this.getScriptPath() + '/node_modules/@libs-scripts-mep/grav-fw-pvi/compat.py') {
return new Promise((resolve) => {
const id = FWLink.PVIEventObserver.add((message, params) => {
const msg = params?.[0]
if (msg.includes("[ESP DEP]")) { Log.warn(msg, Log.Colors.Brown.SandyBrown) }
if (msg.includes("[ESP DEP]") && msg.includes("Package version check and update completed.")) {
FWLink.PVIEventObserver.remove(id)
Log.console("ESP: Dependências instaladas com sucesso.", Log.Colors.Green.SpringGreen)
resolve({ success: true, msg: msg, })
}
}, "PVI.Sniffer.sniffer.PID_")
setTimeout(() => {
FWLink.runInstructionS("EXEC", ["Python", pyFilePath, "true", "true"])
}, 300)
})
}
static { window.GravaFW = GravaFW }
}