Skip to content

Commit

Permalink
Command to flash Tachyon
Browse files Browse the repository at this point in the history
  • Loading branch information
keeramis committed Dec 6, 2024
1 parent ebb29c3 commit 8d62e71
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
Binary file added assets/qdl/qdl
Binary file not shown.
11 changes: 10 additions & 1 deletion src/cli/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ module.exports = ({ commandProcessor, root }) => {
},
'port': {
describe: 'Use this serial port instead of auto-detecting. Useful if there are more than 1 connected device. Only available for serial'
},
'tachyon' : {
boolean: true,
description: 'Flash Tachyon'
},
'verbose' : {
boolean: false,
description: 'Enable logging'
}
},
handler: (args) => {
Expand All @@ -54,7 +62,8 @@ module.exports = ({ commandProcessor, root }) => {
'$0 $command --local application.bin': 'Flash the pre-compiled binary to the device connected over USB',
'$0 $command --local application.zip': 'Flash the pre-compiled binary and assets from the bundle to the device connected over USB',
'$0 $command --local tinker': 'Flash the default Tinker app to the device connected over USB',
'$0 $command --usb firmware.bin': 'Flash the binary over USB'
'$0 $command --usb firmware.bin': 'Flash the binary over USB',
'$0 $command --tachyon /path/to/unpackaged-tool-and-files': 'Flash Tachyon from the files in the specified directory. Use --verbose to see the progress',
},
epilogue: unindent(`
When passing the --local flag, Device OS will be updated if the version on the device is outdated.
Expand Down
94 changes: 93 additions & 1 deletion src/cmd/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const temp = require('temp').track();
const { knownAppNames, knownAppsForPlatform } = require('../lib/known-apps');
const { sourcePatterns, binaryPatterns, binaryExtensions } = require('../lib/file-types');
const deviceOsUtils = require('../lib/device-os-version-util');
const os = require('os');
const semver = require('semver');
const {
createFlashSteps,
Expand All @@ -25,6 +26,7 @@ const {
} = require('../lib/flash-helper');
const createApiCache = require('../lib/api-cache');
const { validateDFUSupport } = require('./device-util');
const execa = require('execa');

module.exports = class FlashCommand extends CLICommandBase {
constructor(...args) {
Expand All @@ -39,9 +41,11 @@ module.exports = class FlashCommand extends CLICommandBase {
target,
port,
yes,
verbose,
tachyon,
'application-only': applicationOnly
}) {
if (!device && !binary && !local) {
if (!tachyon && !device && !binary && !local) {
// if no device nor files are passed, show help
throw usageError('You must specify a device or a file');
}
Expand All @@ -55,11 +59,99 @@ module.exports = class FlashCommand extends CLICommandBase {
} else if (local) {
let allFiles = binary ? [binary, ...files] : files;
await this.flashLocal({ files: allFiles, applicationOnly, target });
} else if (tachyon) {
await this.flashTachyon({ verbose, binary });
} else {
await this.flashCloud({ device, files, target });
}
}

async flashTachyon({ verbose, binary }) {
this.ui.write(`Ensure only one device is connected to a computer${os.EOL}`);

let unpackToolFolder = '';
const stats = await fs.stat(binary);
if (stats.isDirectory()) {
unpackToolFolder = binary;
}
await fs.ensureDir(unpackToolFolder);

const files = await fs.readdir(unpackToolFolder);

const elfFiles = files.filter(f => f.startsWith('prog') && f.endsWith('.elf'));
const rawProgramFiles = files.filter(f => f.startsWith('rawprogram') && f.endsWith('.xml'));
const patchFiles = files.filter(f => f.startsWith('patch') && f.endsWith('.xml'));

if (!elfFiles.length || !rawProgramFiles.length || !patchFiles.length) {
throw new Error('The directory should contain at least one .elf file, one rawprogram file and one patch file');
}

rawProgramFiles.sort((a, b) => {
const aNum = parseInt(a.match(/(\d+).xml/)[1]);
const bNum = parseInt(b.match(/(\d+).xml/)[1]);
return aNum - bNum;
});

patchFiles.sort((a, b) => {
const aNum = parseInt(a.match(/(\d+).xml/)[1]);
const bNum = parseInt(b.match(/(\d+).xml/)[1]);
return aNum - bNum;
});

if (rawProgramFiles.length !== patchFiles.length) {
throw new Error('The number of rawprogram files should match the number of patch files');
}

let filesToProgram = [];
// interleave the rawprogram files and patch files
for (let i = 0; i < rawProgramFiles.length; i++) {
filesToProgram.push(rawProgramFiles[i]);
filesToProgram.push(patchFiles[i]);
}

filesToProgram.unshift(elfFiles[0]);

this.ui.write(`Found the following files in the directory:${os.EOL}`);
this.ui.write('Loader file:');
this.ui.write(` - ${elfFiles[0]}${os.EOL}`);

this.ui.write('Program files:');
for (const file of rawProgramFiles) {
this.ui.write(` - ${file}`);
}
this.ui.write(os.EOL);

this.ui.write('Patch files:');
for (const file of patchFiles) {
this.ui.write(` - ${file}`);
}
this.ui.write(os.EOL);

const qdl = path.join(__dirname, '../../assets/qdl/qdl');
await fs.ensureFile(qdl);

this.ui.write(`Command: ${qdl} --storage ufs ${filesToProgram.join(' ')}${os.EOL}`);
this.ui.write(`Starting download. The download may take several minutes${os.EOL}`);

try {
const res = await execa(qdl, ['--storage', 'ufs', ...filesToProgram], {
cwd: unpackToolFolder,
stdio: verbose ? 'inherit' : 'pipe'
});
// put the output in a log file if not verbose
if (!verbose) {
const outputLog = path.join(process.cwd(), `qdl-${Date.now()}.log`);
await fs.writeFile(outputLog, res.stdout);
this.ui.write(`Download complete. Output log available at ${outputLog}${os.EOL}`);
} else {
this.ui.write(`Download complete${os.EOL}`);
}
} catch (err) {
throw new Error(`Download failed. Try powering up your board in EDL mode and try again.${os.EOL}Error: ${err.message}${os.EOL}`);
}
// TODO: Handle errors
}

async flashOverUsb({ binary, factory }) {
if (utilities.getFilenameExt(binary) === '.zip') {
throw new Error("Use 'particle flash --local' to flash a zipped bundle.");
Expand Down

0 comments on commit 8d62e71

Please sign in to comment.