feat: STM32 Renode 시리얼 출력 수정 + 로그 정리

- uartBuf 버퍼 추가: SSE 연결 전 도착한 UART 데이터 재전송 (타이밍 이슈 해결)
- Renode 로그 라인버퍼링 + ANSI 코드 제거
- 시리얼 모니터에 WARNING/INFO 숨김, Machine started + ERROR만 표시
- ILI9341 mock: &SPI1 → nullptr 패치 (cast-macro address-of 오류 수정)
- STM32 보드 목록: 블루필/블랙필 한국어 표기 + Nucleo 3종 유지

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kim
2026-06-30 13:52:12 +09:00
co-authored by Claude Sonnet 4.6
parent e520d09ca1
commit 5e9596e188
3 changed files with 302 additions and 19 deletions
+37 -3
View File
@@ -3083,8 +3083,8 @@ function _stm32PinResolve(s) {
}
let _renodeGpioBuf = '';
let _stm32LcdInited = false;
function _stm32ParseGpio(raw) {
// 텔레메트리: STX(0x02) "P:name:val" ETX(0x03) 패킷 추출, 나머지는 시리얼로
_renodeGpioBuf += raw;
let out = '';
let i = 0;
@@ -3093,17 +3093,45 @@ function _stm32ParseGpio(raw) {
if (s < 0) { out += _renodeGpioBuf.slice(i); _renodeGpioBuf = ''; break; }
out += _renodeGpioBuf.slice(i, s);
const e = _renodeGpioBuf.indexOf('\x03', s + 1);
if (e < 0) { _renodeGpioBuf = _renodeGpioBuf.slice(s); break; } // 패킷 미완성
const pkt = _renodeGpioBuf.slice(s + 1, e); // "P:PA0:1"
if (e < 0) { _renodeGpioBuf = _renodeGpioBuf.slice(s); break; }
const pkt = _renodeGpioBuf.slice(s + 1, e);
_renodeGpioBuf = _renodeGpioBuf.slice(e + 1);
i = 0;
const parts = pkt.split(':');
if (parts[0] === 'P' && parts.length >= 3)
_stm32UpdatePin(_stm32PinResolve(parts[1]), parts[2]);
else if (parts[0] === 'L' && parts.length >= 3)
_stm32LcdDraw(parts[1], parts.slice(2).join(':'));
}
return out;
}
function _stm32LcdDraw(op, data) {
if (op === 'I') {
const [w, h] = data.split(',').map(Number);
_esp32TftW = w || 240; _esp32TftH = h || 320; _esp32TftCtx2d = null;
_esp32TftDraw('I:' + _esp32TftW + ',' + _esp32TftH);
_stm32LcdInited = true;
return;
}
if (op === 'R') { _esp32TftDraw('R:' + parseInt(data)); return; }
if (!_stm32LcdInited) {
_stm32LcdInited = true;
_esp32TftW = 240; _esp32TftH = 320; _esp32TftCtx2d = null;
_esp32TftDraw('I:240,320');
}
const n = data.split(',').map(Number);
switch (op) {
case 'r': _esp32TftDraw('B:' + n.join(',')); break; // fillRect x,y,w,h,c
case 'h': _esp32TftDraw('B:' + [n[0],n[1],n[2],1,n[3]].join(',')); break; // hline → fillRect h=1
case 'v': _esp32TftDraw('B:' + [n[0],n[1],1,n[2],n[3]].join(',')); break; // vline → fillRect w=1
case 'p': _esp32TftDraw('P:' + n.join(',')); break; // pixel x,y,c
case 'l': _esp32TftDraw('L:' + n.join(',')); break; // line x0,y0,x1,y1,c
case 'c': _esp32TftDraw('C:' + [n[0],n[1],n[2],n[4],n[3]].join(',')); break; // circle cx,cy,r,fill,c → C:cx,cy,r,c,fill
case 't': _esp32TftDraw('T:' + n.join(',')); break; // char x,y,fg,bg,size,charcode
}
}
function _buildBluePillSVG(isF4) {
const leftPins = [
['GND','#666'],['GND','#666'],['3V3','#c0c090'],['NRST','#b0b090'],
@@ -3170,6 +3198,12 @@ function _buildBluePillSVG(isF4) {
function initSTM32RenodeMode(sessionId, fname, fqbn) {
_renodeSessionId = sessionId;
_renodeGpioBuf = '';
_stm32LcdInited = false;
_esp32TftCtx2d = null;
const _tftSec = document.getElementById('tft-section');
if (_tftSec) _tftSec.style.display = 'none';
const _tftDot = document.getElementById('tft-dot');
if (_tftDot) _tftDot.classList.remove('on');
document.querySelector('.header h1').textContent = '🖥️ STM32 Emulator (Renode)';
document.getElementById('filename').textContent = fname;