diff --git a/server/Program.cs b/server/Program.cs index 9e111eb..cfba4f5 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -36,6 +36,18 @@ try options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; }); + // Add CORS policy + builder.Services.AddCors(options => + { + options.AddPolicy("Development", policy => + { + policy + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + // Add Swagger builder.Services.AddControllers(); builder.Services.AddOpenApiDocument(options => @@ -75,6 +87,7 @@ try app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); + app.UseCors(); app.UseAuthorization(); // if (app.Environment.IsDevelopment()) diff --git a/server/src/Common.cs b/server/src/Common.cs index bc126ef..7cee773 100644 --- a/server/src/Common.cs +++ b/server/src/Common.cs @@ -175,4 +175,15 @@ namespace Common } + public class String + { + public static string Reverse(string s) + { + char[] charArray = s.ToCharArray(); + Array.Reverse(charArray); + return new string(charArray); + } + + } + } diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs index 23a0db9..fc6ed81 100644 --- a/server/src/Controllers.cs +++ b/server/src/Controllers.cs @@ -1,6 +1,6 @@ using System.Net; using Common; -using DotNext; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using WebProtocol; @@ -196,6 +196,62 @@ public class JtagController : ControllerBase } } + /// <summary> + /// 获取状态寄存器 + /// </summary> + /// <param name="address"> 设备地址 </param> + /// <param name="port"> 设备端口 </param> + [HttpGet("ReadStatusReg")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask<IResult> ReadStatusReg(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.ReadStatusReg(); + + if (ret.IsSuccessful) + { + var binaryValue = Common.String.Reverse(Convert.ToString(ret.Value, 2).PadLeft(32, '0')); + logger.Info($"Read device {address} Status Register: 0b{binaryValue}"); + return TypedResults.Ok(new + { + original = ret.Value, + binary = binaryValue, + id_err = binaryValue[0], + crc_err = binaryValue[1], + aut_err = binaryValue[2], + rbcrc_err = binaryValue[3], + timeout = binaryValue[4], + wakeup_over = binaryValue[5], + wakedown_over = binaryValue[6], + m = Common.String.Reverse(binaryValue[7..10]), + init_complete = binaryValue[10], + init_n = binaryValue[11], + done = binaryValue[12], + done_i = binaryValue[13], + glogen = binaryValue[14], + glogen_fb = binaryValue[15], + gouten = binaryValue[16], + grsn = binaryValue[17], + gwen = binaryValue[18], + pll_lock = binaryValue[19], + fallback = binaryValue[21], + ipal_m = Common.String.Reverse(binaryValue[22..24]), + flg_x8 = binaryValue[24], + flg_x16 = binaryValue[25], + flg_x32 = binaryValue[26], + over_temp = binaryValue[27], + prcfg_err = binaryValue[28], + prcfg_over = binaryValue[29], + }); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + /// <summary> /// 上传比特流文件 /// </summary> @@ -312,6 +368,7 @@ public class Log : ControllerBase private readonly string _logFilePath = Directory.GetFiles(Directory.GetCurrentDirectory())[0]; + [EnableCors("Development")] [HttpGet] public async Task<IActionResult> Index() { @@ -373,28 +430,27 @@ public class Log : ControllerBase await Response.Body.FlushAsync(); } - [HttpGet("example")] - public async Task<IActionResult> SseExample() - { - // 请求头 - Response.Headers.Add("Content-Type", "text/event-stream"); - Response.Headers.Add("Cache-Control", "no-cache"); - Response.Headers.Add("Connection", "keep-alive"); - - // 假设不断得到新数据 - for (int i = 0; i < 10000; i++) - { - // 每个数据参照 SSE 返回数据格式进行组装 - var content = "event: message\n" - + "data: {\"color\":\"66ccff\"}\n\n"; - - // 立刻写入响应 - await Response.WriteAsync(content); - await Response.Body.FlushAsync(); - } - - // 结束 - return new EmptyResult(); - } + // [EnableCors("Development")] + // [HttpGet("example")] + // public async Task<IActionResult> SseExample(HttpContext ctx, ItemService service, CancellationToken ct) + // { + // // 请求头 + // ctx.Response.Headers.Add("Content-Type", "text/event-stream"); + // // Response.Headers.Add("Content-Type", "text/event-stream"); + // // Response.Headers.Add("Cache-Control", "no-cache"); + // // Response.Headers.Add("Connection", "keep-alive"); + // + // while (!ct.IsCancellationRequested) + // { + // var item = await service.WaitForNewItem(); + // + // await ctx.Response.WriteAsync($"data: "); + // await JsonSerializer.SerializeAsync(ctx.Response.Body, item); + // await ctx.Response.WriteAsync($"\n\n"); + // await ctx.Response.Body.FlushAsync(); + // + // service.Reset(); + // } + // } } diff --git a/server/src/JtagClient.cs b/server/src/JtagClient.cs index 07a3468..b4581ff 100644 --- a/server/src/JtagClient.cs +++ b/server/src/JtagClient.cs @@ -596,6 +596,40 @@ public class Jtag return retData.Value; } + public async ValueTask<Result<uint>> ReadStatusReg() + { + // Clear Data + await MsgBus.UDPServer.ClearUDPData(this.address); + + logger.Trace($"Clear up udp server {this.address} receive data"); + + Result<bool> ret; + + ret = await ClearAllRegisters(); + if (!ret.IsSuccessful) return new(ret.Error); + else if (!ret.Value) return new(new Exception("Jtag Clear All Registers Failed")); + + ret = await RunTest(); + if (!ret.IsSuccessful) return new(ret.Error); + else if (!ret.Value) return new(new Exception("Jtag Run Test Failed")); + + ret = await ExecRDCmd(JtagCmd.JTAG_DR_RDSR); + if (!ret.IsSuccessful) return new(ret.Error); + else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_RDSR Failed")); + + ret = await ClearWriteDataReg(); + if (!ret.IsSuccessful) return new(ret.Error); + else if (!ret.Value) return new(new Exception("Jtag Clear Write Registers Failed")); + + var retData = await LoadDRCareOutput(4); + if (!retData.IsSuccessful) + { + return new(new Exception("Read Status Reg Failed")); + } + + return retData.Value; + } + public async ValueTask<Result<bool>> DownloadBitstream(byte[] bitstream) { // Clear Data diff --git a/src/views/JtagTest.vue b/src/views/JtagTest.vue index c20d582..8337c9b 100644 --- a/src/views/JtagTest.vue +++ b/src/views/JtagTest.vue @@ -3,13 +3,45 @@ <div class="h-full w-32"></div> <div class="h-full w-[70%] shadow-2xl flex"> - + <p>{{ logText }}</p> + <button class="btn btn-primary h-10 w-30">获取ID Code</button> </div> </div> </template> -<script lang="ts" setup></script> +<script lang="ts" setup> +import { ref } from "vue"; +const eventSource = new EventSource("http://localhost:5000/api/log"); +const logText = ref(""); + +// 启动SSE连接 +function startStream() { + eventSource.onmessage = function (e) { + logText.value = e.data; + }; + + eventSource.onerror = function (err) { + console.error("Error:", err); + eventSource.close(); + }; + + eventSource.onopen = function () { + console.log("Connection opened"); + }; +} + +// 停止SSE连接 +function stopStream() { + if (eventSource) { + eventSource.close(); + console.log("Connection closed"); + } +} + +// 页面加载时自动启动 +window.onload = startStream; +</script> <style scoped lang="postcss"> @import "../assets/main.css";