From bab3e086e94448c4183c8d70e310cb71a260bd20 Mon Sep 17 00:00:00 2001 From: Kizarm Date: Fri, 15 Mar 2024 15:13:20 +0100 Subject: [PATCH] add debug over minichlink --- README.md | 5 +++ debug/Makefile | 53 ++++++++++++++++++++++++++++++++ debug/ch32v003 | 1 + debug/common | 1 + debug/debug.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ debug/debug.h | 11 +++++++ debug/main.cpp | 21 +++++++++++++ 7 files changed, 173 insertions(+) create mode 100644 debug/Makefile create mode 120000 debug/ch32v003 create mode 120000 debug/common create mode 100644 debug/debug.cpp create mode 100644 debug/debug.h create mode 100644 debug/main.cpp diff --git a/README.md b/README.md index 238c43d..2afed82 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,8 @@ typu melodický zvonek, piánko atd. to stačí. Výhoda je, že piny vydrží 2 je možné připojit 30 Ohm sluchátka (do série) plus sériový odpor 100 Ohm mezi piny PD0 a PD2 a hraje to s dostatečnou hlasitostí a docela čistě. +## debug +Debug přes jednodrátové rozhraní WCH Link. +Je to pomalé a divné, ale funguje to. Sice nevím jak, +ale je to celkem jedno. Fakticky je to kompletně +převzato z https://github.com/cnlohr/ch32v003fun. diff --git a/debug/Makefile b/debug/Makefile new file mode 100644 index 0000000..4bdd97f --- /dev/null +++ b/debug/Makefile @@ -0,0 +1,53 @@ +# ch32v003 +TARGET?= ch32v003 +TOOL ?= gcc +#TOOL ?= clang + + +PRJ = example + +VPATH = . ./$(TARGET) ./common +BLD = ./build/ +DFLAGS = -S +LFLAGS = -g +LDLIBS = +BFLAGS = --strip-unneeded + +CFLAGS = -MMD -Wall -ggdb -fno-exceptions -ffunction-sections -fdata-sections +CFLAGS+= -I. -I./$(TARGET) -I./common -I/usr/include/newlib +DEL = rm -f + +# zdrojaky +OBJS = main.o debug.o print.o + +include $(TARGET)/$(TOOL).mk +BOBJS = $(addprefix $(BLD),$(OBJS)) + +all: $(BLD) $(PRJ).elf +# ... atd. +-include $(BLD)*.d +# linker +$(PRJ).elf: $(BOBJS) + -@echo [LD $(TOOL),$(TARGET)] $@ + @$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(LDLIBS) + -@echo "size:" + @$(SIZE) $(PRJ).elf + -@echo "listing:" + $(DUMP) $(DFLAGS) $(PRJ).elf > $(PRJ).lst + -@echo "OK." + $(COPY) $(BFLAGS) -O binary $(PRJ).elf $(PRJ).bin +# preloz co je potreba +$(BLD)%.o: %.c + -@echo [CC $(TOOL),$(TARGET)] $@ + @$(CC) -c $(CFLAGS) $< -o $@ +$(BLD)%.o: %.cpp + -@echo [CX $(TOOL),$(TARGET)] $@ + @$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@ +$(BLD): + mkdir $(BLD) +flash: $(PRJ).elf + minichlink -w $(PRJ).bin flash -b +# vycisti +clean: + $(DEL) $(BLD)* *.lst *.bin *.elf *.map *~ +.PHONY: all clean diff --git a/debug/ch32v003 b/debug/ch32v003 new file mode 120000 index 0000000..0bcf9a1 --- /dev/null +++ b/debug/ch32v003 @@ -0,0 +1 @@ +../ch32v003/ \ No newline at end of file diff --git a/debug/common b/debug/common new file mode 120000 index 0000000..8332399 --- /dev/null +++ b/debug/common @@ -0,0 +1 @@ +../common/ \ No newline at end of file diff --git a/debug/debug.cpp b/debug/debug.cpp new file mode 100644 index 0000000..f6773c3 --- /dev/null +++ b/debug/debug.cpp @@ -0,0 +1,81 @@ +#include "system.h" +#include "debug.h" + +struct DEBUG_S { + uint32_t UNUSED0; + volatile uint32_t DATA0; + volatile uint32_t DATA1; +}; +static DEBUG_S & DBGM = * reinterpret_cast (0xe00000f0); +static constexpr unsigned FUNCONF_DEBUGPRINTF_TIMEOUT = 160000u; +// Převzato i když jsem to nekontroloval. Ono je to dost divoké. +extern "C" { + void handle_debug_input( int numbytes, uint8_t * data ) __attribute__((used,weak)); + void handle_debug_input( int numbytes, uint8_t * data ) { } + void internal_handle_input( volatile uint32_t * dmdata0 ) { + uint32_t dmd0 = * dmdata0; + int bytes = (dmd0 & 0x3f) - 4; + if( bytes > 0 ) { + handle_debug_input( bytes, ((uint8_t*)dmdata0) + 1 ); + } + } +}; +// where [status word] is: +// b7 = is a "printf" waiting? +// b0..b3 = # of bytes in printf (+4). (5 or higher indicates a print of some kind) +// note: if b7 is 0 in reply, but b0..b3 have >=4 then we received data from host. +static int _write (const char * buf, const int size) { + char buffer[4] = { 0 }; + int place = 0; + uint32_t lastdmd; + uint32_t timeout = FUNCONF_DEBUGPRINTF_TIMEOUT; // Give up after ~40ms + + if( size == 0 ) { + lastdmd = DBGM.DATA0; + if( lastdmd && !(lastdmd & 0x80) ) internal_handle_input( (uint32_t*) & DBGM.DATA0 ); + } + while( place < size ) { + int tosend = size - place; + if( tosend > 7 ) tosend = 7; + + while( ( lastdmd = DBGM.DATA0 ) & 0x80 ) + if( timeout-- == 0 ) return place; + + if( lastdmd ) internal_handle_input( (uint32_t*) & DBGM.DATA0 ); + + timeout = FUNCONF_DEBUGPRINTF_TIMEOUT; + + int t = 3; + while( t < tosend ) { + buffer[t-3] = buf[t+place]; + t++; + } + DBGM.DATA1 = *(uint32_t*)&(buffer[0]); + t = 0; + while( t < tosend && t < 3 ) { + buffer[t+1] = buf[t+place]; + t++; + } + buffer[0] = 0x80 | (tosend + 4); + DBGM.DATA0 = *(uint32_t*)&(buffer[0]); + + //buf += tosend; + place += tosend; + } + return size; +} + +Debug::Debug() noexcept : BaseLayer() { + // Clear out the sending flag. + DBGM.DATA1 = 0u; + DBGM.DATA0 = 0x80u; + // Tohle je asi zbytečné. + while ( DBGM.DATA0 & 0x80 ); +} +uint32_t Debug::Down(const char * buf, const uint32_t size) { + /* Z nějakého záhadného důvodu pokud namastím kód přímo sem, + * optimalizace ho vyhodí. Nějak se to nesnáší s virtuálními + * metodami. + * */ + return _write (buf, size); +} diff --git a/debug/debug.h b/debug/debug.h new file mode 100644 index 0000000..2083e82 --- /dev/null +++ b/debug/debug.h @@ -0,0 +1,11 @@ +#ifndef DEBUG_H +#define DEBUG_H +#include "baselayer.h" + +class Debug : public BaseLayer { + public: + explicit Debug () noexcept; + uint32_t Down (const char * buf, const uint32_t size) override; +}; + +#endif // DEBUG_H diff --git a/debug/main.cpp b/debug/main.cpp new file mode 100644 index 0000000..2e73a62 --- /dev/null +++ b/debug/main.cpp @@ -0,0 +1,21 @@ +#include "print.h" +#include "debug.h" +////////////////////////////////////////////////////// +/* Debug přes jednodrátové rozhraní WCH Link. + * Je to pomalé a divné, ale funguje to. Sice nevím jak, + * ale je to celkem jedno. Fakticky je to kompletně + * převzato z https://github.com/cnlohr/ch32v003fun. + * */ +////////////////////////////////////////////////////// +static int n = 0; +int main () { + Print cout (DEC); + Debug debug; + cout += debug; + cout << "Begin tests ... \n"; + for (;;) { + cout << "pass: " << n << "\n"; + n += 1u; + } + return 0; +}