fix: boundary scan could not save
This commit is contained in:
parent
ba6ec73b84
commit
a6ac728cf1
|
@ -10,6 +10,7 @@
|
|||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.2.4",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"async-mutex": "^0.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"log-symbols": "^7.0.0",
|
||||
"mathjs": "^14.4.0",
|
||||
|
@ -2006,6 +2007,15 @@
|
|||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/async-mutex": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz",
|
||||
"integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.21",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
|
||||
|
@ -3700,6 +3710,12 @@
|
|||
"integrity": "sha512-HjX/7HxQe2bXkbp8pHTjy4Ir9eHIDnDDsLDphhGqy6I9iZ/vD4QXWEIlrVRZsEX+kS2jIiiF/mnl0nKnPTiYFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typed-function": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.1.tgz",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.2.4",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"async-mutex": "^0.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"log-symbols": "^7.0.0",
|
||||
"mathjs": "^14.4.0",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -99,7 +99,6 @@ async function handleClick(event: Event): Promise<void> {
|
|||
isUploading.value = true;
|
||||
try {
|
||||
const ret = await props.uploadEvent(bitstream.value);
|
||||
console.debug(`After upload bistream: ${bitstream.value}, result: ${ret}`);
|
||||
if (isUndefined(props.downloadEvent)) {
|
||||
if (ret) {
|
||||
dialog.info("上传成功");
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-center text-2xl">Jtag</h1>
|
||||
<div class="flex flex-col">
|
||||
<p class="grow">Jtag Addr: {{ props.jtagAddr }}</p>
|
||||
<p class="grow">Jtag Port: {{ props.jtagPort?.toString() }}</p>
|
||||
<p class="grow">Jtag Addr: {{ eqps.boardAddr }}</p>
|
||||
<p class="grow">Jtag Port: {{ eqps.boardPort.toString() }}</p>
|
||||
<div class="flex justify-between grow">
|
||||
<p>IDCode: 0x{{ jtagIDCode.toString(16).padStart(8, "0") }}</p>
|
||||
<p>IDCode: 0x{{ jtagIDCode.toString(16).padStart(8, "0").toUpperCase() }}</p>
|
||||
<button class="btn btn-circle w-6 h-6" :onclick="getIDCode">
|
||||
<svg class="icon opacity-70 fill-primary" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="4865" width="200" height="200">
|
||||
|
@ -17,27 +17,30 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<UploadCard class="bg-base-200" :upload-event="uploadBitstream" :download-event="downloadBitstream"
|
||||
:bitstream-file="eqps.jtagBitstream" @update:bitstream-file="handleBitstreamChange">
|
||||
<UploadCard class="bg-base-200" :upload-event="eqps.jtagUploadBitstream"
|
||||
:download-event="eqps.jtagDownloadBitstream" :bitstream-file="eqps.jtagBitstream"
|
||||
@update:bitstream-file="handleBitstreamChange">
|
||||
</UploadCard>
|
||||
<div class="divider"></div>
|
||||
<button class="btn w-full btn-primary" :class="isEnableJtagBoundaryScan ? '' : 'btn-soft'"
|
||||
<fieldset class="fieldset w-full">
|
||||
<legend class="fieldset-legend text-sm">边界扫描刷新率 / Hz</legend>
|
||||
<input type="number" class="input validator w-full" required placeholder="Type a number between 1 to 1000" min="1"
|
||||
max="1000" v-model="jtagBoundaryScanFreq" title="Type a number between 1 to 1000" />
|
||||
<p class="validator-hint">输入一个1 ~ 1000的数</p>
|
||||
</fieldset>
|
||||
<button class="btn w-full btn-primary" :class="eqps.enableJtagBoundaryScan ? '' : 'btn-soft'"
|
||||
:onclick="toggleJtagBoundaryScan">
|
||||
{{ isEnableJtagBoundaryScan ? "关闭边界扫描" : "启动边界扫描" }}
|
||||
{{ eqps.enableJtagBoundaryScan ? "关闭边界扫描" : "启动边界扫描" }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { JtagClient } from "@/APIClient";
|
||||
import z from "zod";
|
||||
import UploadCard from "@/components/UploadCard.vue";
|
||||
import { useDialogStore } from "@/stores/dialog";
|
||||
import { Common } from "@/Common";
|
||||
import { useEquipments } from "@/stores/equipments";
|
||||
import { useConstraintsStore } from "@/stores/constraints";
|
||||
import { isUndefined } from "lodash";
|
||||
import { ref, watchEffect } from "vue";
|
||||
import { computed, ref, watchEffect } from "vue";
|
||||
|
||||
interface CapsProps {
|
||||
jtagAddr?: string;
|
||||
|
@ -48,107 +51,38 @@ const props = withDefaults(defineProps<CapsProps>(), {});
|
|||
|
||||
// Global Stores
|
||||
const dialog = useDialogStore();
|
||||
const constrainsts = useConstraintsStore();
|
||||
const eqps = useEquipments();
|
||||
|
||||
const jtagController = new JtagClient();
|
||||
const isEnableJtagBoundaryScan = ref(false);
|
||||
const jtagBoundaryScanFreq = computed({
|
||||
get: () => eqps.jtagBoundaryScanFreq,
|
||||
set: (val) => {
|
||||
if (z.number().positive().max(1000).safeParse(val).success)
|
||||
eqps.jtagBoundaryScanFreq = val;
|
||||
},
|
||||
});
|
||||
|
||||
// 使用传入的属性或默认值
|
||||
const jtagIDCode = ref(0);
|
||||
const jtagIDCode = ref(0xffff_ffff);
|
||||
|
||||
function handleBitstreamChange(file: File | undefined) {
|
||||
eqps.jtagBitstream = file;
|
||||
}
|
||||
|
||||
async function toggleJtagBoundaryScan() {
|
||||
isEnableJtagBoundaryScan.value = !isEnableJtagBoundaryScan.value;
|
||||
if (isEnableJtagBoundaryScan.value) jtagBoundaryScan();
|
||||
}
|
||||
|
||||
async function jtagBoundaryScan() {
|
||||
try {
|
||||
const portStates = await jtagController.boundaryScanLogicalPorts(
|
||||
props.jtagAddr,
|
||||
props.jtagPort,
|
||||
);
|
||||
|
||||
constrainsts.batchSetConstraintStates(portStates);
|
||||
} catch (error) {
|
||||
dialog.error("边界扫描发生错误");
|
||||
console.error(error);
|
||||
isEnableJtagBoundaryScan.value = false;
|
||||
} finally {
|
||||
if (isEnableJtagBoundaryScan.value) setTimeout(jtagBoundaryScan, 50);
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadBitstream(bitstream: File): Promise<boolean> {
|
||||
if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
|
||||
dialog.error("开发板地址或端口空缺");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
console.debug(`Before upload bistream: ${bitstream}`);
|
||||
const resp = await jtagController.uploadBitstream(
|
||||
props.jtagAddr,
|
||||
Common.toFileParameterOrNull(bitstream),
|
||||
);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
dialog.error("上传错误");
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadBitstream(): Promise<boolean> {
|
||||
if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
|
||||
dialog.error("开发板地址或端口空缺");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const resp = await jtagController.downloadBitstream(
|
||||
props.jtagAddr,
|
||||
props.jtagPort,
|
||||
);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
dialog.error("上传错误");
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getIDCode(isQuiet: boolean = false) {
|
||||
if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
|
||||
dialog.error("开发板地址或端口空缺");
|
||||
if (eqps.jtagClientMutex.isLocked()) {
|
||||
dialog.warn("Jtag正在被占用");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const resp = await jtagController.getDeviceIDCode(
|
||||
props.jtagAddr,
|
||||
props.jtagPort,
|
||||
);
|
||||
jtagIDCode.value = resp;
|
||||
} catch (e) {
|
||||
if (!isQuiet) dialog.error("获取IDCode错误");
|
||||
}
|
||||
eqps.enableJtagBoundaryScan = !eqps.enableJtagBoundaryScan;
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
eqps.setAddr(props.jtagAddr);
|
||||
eqps.setPort(props.jtagPort);
|
||||
});
|
||||
async function getIDCode(isQuiet: boolean = false) {
|
||||
jtagIDCode.value = await eqps.jtagGetIDCode(isQuiet);
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (
|
||||
z.string().ip().safeParse(props.jtagAddr).success &&
|
||||
z.number().positive().safeParse(props.jtagPort).success
|
||||
)
|
||||
watchEffect(async () => {
|
||||
if (eqps.setAddr(props.jtagAddr) && eqps.setPort(props.jtagPort))
|
||||
getIDCode(true);
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,40 +1,140 @@
|
|||
import { ref, computed } from 'vue'
|
||||
import { ref, watchEffect } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { isString, isUndefined, toNumber } from 'lodash';
|
||||
import { isString, toNumber, isUndefined } from 'lodash';
|
||||
import { Common } from '@/Common';
|
||||
import z from "zod"
|
||||
import { isNumber } from 'mathjs';
|
||||
import { JtagClient } from "@/APIClient";
|
||||
import { Mutex, withTimeout } from 'async-mutex';
|
||||
import { useConstraintsStore } from "@/stores/constraints";
|
||||
import { useDialogStore } from './dialog';
|
||||
|
||||
export const useEquipments = defineStore('equipments', () => {
|
||||
const boardAddr = ref("127.0.0.1")
|
||||
const boardPort = ref(1234)
|
||||
const jtagBitstream = ref<File>()
|
||||
// Global Stores
|
||||
const constrainsts = useConstraintsStore();
|
||||
const dialog = useDialogStore();
|
||||
|
||||
function setAddr(address: string | undefined) {
|
||||
if (isUndefined(address)) return;
|
||||
if (z.string().ip("4").safeParse(address).success)
|
||||
const boardAddr = ref("127.0.0.1");
|
||||
const boardPort = ref(1234);
|
||||
const jtagBitstream = ref<File>();
|
||||
const jtagBoundaryScanFreq = ref(10);
|
||||
const jtagClientMutex = withTimeout(new Mutex(), 2000, new Error("JtagClient Mutex Timeout!"))
|
||||
const jtagClient = new JtagClient();
|
||||
|
||||
const enableJtagBoundaryScan = ref(false);
|
||||
|
||||
function setAddr(address: string | undefined): boolean {
|
||||
if (isString(address) && z.string().ip("4").safeParse(address).success) {
|
||||
boardAddr.value = address;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function setPort(port: string | number | undefined) {
|
||||
if (isUndefined(port)) return;
|
||||
|
||||
function setPort(port: string | number | undefined): boolean {
|
||||
if (isString(port) && port.length != 0) {
|
||||
const portNumber = toNumber(port);
|
||||
if (z.number().nonnegative().max(65535).safeParse(portNumber).success)
|
||||
if (z.number().nonnegative().max(65535).safeParse(portNumber).success) {
|
||||
boardPort.value = portNumber;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (isNumber(port)) {
|
||||
if (z.number().nonnegative().max(65535).safeParse(port).success)
|
||||
if (z.number().nonnegative().max(65535).safeParse(port).success) {
|
||||
boardPort.value = port;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (enableJtagBoundaryScan.value) jtagBoundaryScan();
|
||||
});
|
||||
|
||||
async function jtagBoundaryScan() {
|
||||
const release = await jtagClientMutex.acquire();
|
||||
try {
|
||||
const portStates = await jtagClient.boundaryScanLogicalPorts(
|
||||
boardAddr.value,
|
||||
boardPort.value,
|
||||
);
|
||||
|
||||
constrainsts.batchSetConstraintStates(portStates);
|
||||
} catch (error) {
|
||||
dialog.error("边界扫描发生错误");
|
||||
console.error(error);
|
||||
enableJtagBoundaryScan.value = false;
|
||||
} finally {
|
||||
release();
|
||||
|
||||
if (enableJtagBoundaryScan.value)
|
||||
setTimeout(jtagBoundaryScan, 1000 / jtagBoundaryScanFreq.value);
|
||||
}
|
||||
}
|
||||
|
||||
async function jtagUploadBitstream(bitstream: File): Promise<boolean> {
|
||||
try {
|
||||
const resp = await jtagClient.uploadBitstream(
|
||||
boardAddr.value,
|
||||
Common.toFileParameterOrNull(bitstream),
|
||||
);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
dialog.error("上传错误");
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function jtagDownloadBitstream(): Promise<boolean> {
|
||||
const release = await jtagClientMutex.acquire();
|
||||
try {
|
||||
const resp = await jtagClient.downloadBitstream(
|
||||
boardAddr.value,
|
||||
boardPort.value
|
||||
);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
dialog.error("上传错误");
|
||||
console.error(e);
|
||||
return false;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
async function jtagGetIDCode(isQuiet: boolean = false): Promise<number> {
|
||||
const release = await jtagClientMutex.acquire();
|
||||
try {
|
||||
const resp = await jtagClient.getDeviceIDCode(
|
||||
boardAddr.value,
|
||||
boardPort.value
|
||||
);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
if (!isQuiet) dialog.error("获取IDCode错误");
|
||||
return 0xffff_ffff;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
boardAddr,
|
||||
boardPort,
|
||||
setAddr,
|
||||
setPort,
|
||||
jtagBitstream,
|
||||
jtagBoundaryScanFreq,
|
||||
jtagClientMutex,
|
||||
jtagClient,
|
||||
jtagUploadBitstream,
|
||||
jtagDownloadBitstream,
|
||||
jtagGetIDCode,
|
||||
enableJtagBoundaryScan,
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ async function uploadBitstream(bitstream: File): Promise<boolean> {
|
|||
}
|
||||
|
||||
try {
|
||||
console.debug(`Before upload bistream: ${bitstream}`);
|
||||
const resp = await jtagController.uploadBitstream(
|
||||
boardAddress.value,
|
||||
Common.toFileParameterOrNull(bitstream),
|
||||
|
|
Loading…
Reference in New Issue