Skip to content

Commit

Permalink
Fix compile, and tweak wait for debugger work.
Browse files Browse the repository at this point in the history
Change behavior to:
1. Printf will wait up to 120ms at boot.
2. If printf has timed out, it will immediately continue.
3. If a debugger is reattached, it will keep printing.
4. If a debugger is attached, it will wait up to 120ms. Then continue at full speed.

Fix GDB on minichlink.
Update minichlink.exe
Add `make gdbclient` as a target and change single step behavior.
Further tweaks to vs code launch (need to backport to template). And, also, improvements to windows GDB.
 * Optimize pgm-esp32-s2-ch32xx.c
 * Improve VS Code build
 * Fix stepping for older GDBs
Properly define flash memory section.
  • Loading branch information
cnlohr committed Nov 16, 2024
1 parent d2a3861 commit ec36cfc
Show file tree
Hide file tree
Showing 17 changed files with 352 additions and 138 deletions.
47 changes: 34 additions & 13 deletions ch32v003fun/ch32v003fun.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,10 +761,13 @@ extern uint32_t * _edata;
// If you don't override a specific handler, it will just spin forever.
void DefaultIRQHandler( void )
{
#if FUNCONF_DEBUG_HARDFAULT
// Wait indefinitely for a debugger to attach.
while( !DidDebuggerAttach() );
printf( "DefaultIRQHandler MSTATUS:%08x MTVAL:%08x MCAUSE:%08x MEPC:%08x\n", (int)__get_MSTATUS(), (int)__get_MTVAL(), (int)__get_MCAUSE(), (int)__get_MEPC() );
#if FUNCONF_DEBUG_HARDFAULT && ( FUNCONF_USE_DEBUGPRINTF || FUNCONF_USE_UARTPRINTF )
#if FUNCONF_USE_DEBUGPRINTF
// Wait indefinitely for a printf to become clear.
while( !DebugPrintfBufferFree() );

#endif
printf( "DEAD MSTATUS:%08x MTVAL:%08x MCAUSE:%08x MEPC:%08x\n", (int)__get_MSTATUS(), (int)__get_MTVAL(), (int)__get_MCAUSE(), (int)__get_MEPC() );
#endif
// Infinite Loop
asm volatile( "1: j 1b" );
Expand Down Expand Up @@ -1587,7 +1590,7 @@ static void internal_handle_input( volatile uint32_t * dmdata0 )
{
uint32_t dmd0 = *dmdata0;
int bytes = (dmd0 & 0x3f) - 4;
if( bytes > 0 )
if( bytes > 0 && bytes < 16 )
{
handle_debug_input( bytes, ((uint8_t*)dmdata0) + 1 );
}
Expand All @@ -1609,14 +1612,18 @@ void poll_input( void )
// MSB .... LSB
// DMDATA0: char3 char2 char1 [status word]
// 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)
// bit 7 = is a "printf" waiting?
// bit 6 = printf has timed out.
// bit 0..bit 3 = # 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.
// Special sentinel:
// status word = 0x80 = default at start
// status word = 0xcx = timed out.
// declare as weak to allow overriding.
WEAK int _write(int fd, const char *buf, int size)
{
(void)fd;
if( !DidDebuggerAttach() ) return;
if( ( *DMDATA0 & 0xc0 ) == 0xc0 ) return 0;

char buffer[4] = { 0 };
int place = 0;
Expand All @@ -1634,7 +1641,13 @@ WEAK int _write(int fd, const char *buf, int size)
if( tosend > 7 ) tosend = 7;

while( ( lastdmd = (*DMDATA0) ) & 0x80 )
if( timeout-- == 0 ) return place;
{
if( timeout-- == 0 )
{
*DMDATA0 |= 0xc0;
return 0;
}
}

if( lastdmd ) internal_handle_input( (uint32_t*)DMDATA0 );

Expand Down Expand Up @@ -1665,24 +1678,32 @@ WEAK int _write(int fd, const char *buf, int size)
// single to debug intf
WEAK int putchar(int c)
{
if( !DidDebuggerAttach() ) return;
if( ( *DMDATA0 & 0xc0 ) == 0xc0 ) return 0;

int timeout = FUNCONF_DEBUGPRINTF_TIMEOUT;
uint32_t lastdmd = 0;

while( ( lastdmd = (*DMDATA0) ) & 0x80 )
if( timeout-- == 0 ) return 0;
{
if( timeout-- == 0 )
{
*DMDATA0 |= 0xc0;
return 0;
}
}

// Simply seeking input.
if( lastdmd ) internal_handle_input( (uint32_t*)DMDATA0 );

// Write out character.
*DMDATA0 = 0x85 | ((const char)c<<8);
return 1;
}

void SetupDebugPrintf( void )
{
// Clear out the sending flag.
*DMDATA1 = 0x0;
*DMDATA1 = 0x00;
*DMDATA0 = 0x80;
}

Expand All @@ -1706,7 +1727,7 @@ int WaitForDebuggerToAttach( int timeout_ms )

// Wait for the sentinel to become zero.
while( !DidDebuggerAttach() ) {
if( (SYSTICKCNT - start) > timeout ) return 1;
if( timeout_ms && (SYSTICKCNT - start) > timeout ) return 1;
}

return 0;
Expand Down
18 changes: 17 additions & 1 deletion ch32v003fun/ch32v003fun.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@
7. Hardware MMIO structs, i.e.
SysTick->CNT = current system tick counter (can be Hclk or Hclk/8)
TIM2->CH1CVR = direct control over a PWM output

8. Default debug behavior, when semihosting:
a. You get access to DidDebuggerAttach() - so you can see if a debugger has attached.
b. WaitForDebuggerToAttach( int timeout_ms ) - if timeout_ms == 0, will wait for forever.
c. printf will wait 120ms (configurable) to make sure it doesn't drop data. Otherwise,
printf will fast-path to exit after the first timeout. It will still do the string
formatting, but will not wait on output. Timeout is configured with
FUNCONF_DEBUGPRINTF_TIMEOUT.
d. If you hard fault, it will wait indefinitely for a debugger to attach, once attached,
will printf the fault cause, and the memory address of the fault. Space can be saved
by setting FUNCONF_DEBUG_HARDFAULT to 0.
*/


Expand Down Expand Up @@ -13991,10 +14002,15 @@ void SystemInit(void);
void SetupUART( int uartBRR );

// Returns 1 if timeout reached, 0 otherwise.
// If timeout_ms == 0, wait indefinitely.
// Use DidDebuggerAttach() For a zero-wait way of seeing if it attached.
int WaitForDebuggerToAttach( int timeout_ms );

// Returns 1 if a debugger has activated the debug module.
static int DidDebuggerAttach() { return !*DMSTATUS_SENTINEL; }
#define DidDebuggerAttach() (!*DMSTATUS_SENTINEL)

// Returns 1 if a debugger has activated the debug module.
#define DebugPrintfBufferFree() (!(*DMDATA0 & 0x80))

// Just a definition to the internal _write function.
int _write(int fd, const char *buf, int size);
Expand Down
3 changes: 3 additions & 0 deletions ch32v003fun/ch32v003fun.mk
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ unbrick :
gdbserver :
-$(MINICHLINK)/minichlink -baG

gdbclient :
gdb-multiarch $(TARGET).elf -ex "target remote :2000"

clangd :
make clean
bear -- make build
Expand Down
19 changes: 17 additions & 2 deletions examples/debugprintfdemo/.vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cppStandard": "c++14",
"cppStandard": "c++20",
"intelliSenseMode": "linux-clang-x64",
"compilerArgs": [
"-DCH32V003FUN_BASE"
],
"configurationProvider": "ms-vscode.makefile-tools"
},
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/../../ch32v003fun"
],
"defines": [],
"compilerPath": "riscv64-unknown-elf-gcc-10.1.0.exe",
"cppStandard": "c++20",
"compilerArgs": [
"-DCH32V003FUN_BASE"
],
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
"version": 4,
"enableConfigurationSquiggles": true
}
10 changes: 2 additions & 8 deletions examples/debugprintfdemo/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"deploySteps": [
{
"type": "shell",
"continueOn": "GDBServer",
"command": "make --directory=${workspaceFolder} closechlink flash gdbserver"
},
],
"preLaunchTask": "run_flash_and_gdbserver",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
Expand All @@ -33,7 +27,7 @@
"type": "node",
"request": "launch",
"program": "",
"preLaunchTask": "run_flash_and_gdbserver",
"preLaunchTask": "run_flash_and_monitor",
}
]
}
14 changes: 13 additions & 1 deletion examples/debugprintfdemo/.vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,22 @@
},
"command": "make closechlink flash",
},
{
"type": "shell",
"label": "run_flash_and_monitor",
"presentation": {
"echo": true,
"focus": false,
"group": "build",
"panel": "shared",
"showReuseMessage" : false
},
"command": "make flash monitor",
},
{
"type": "shell",
"label": "run_flash_and_gdbserver",
"command": "make closechlink flash gdbserver",
"command": "make flash gdbserver",

"presentation": {
"echo": true,
Expand Down
2 changes: 2 additions & 0 deletions examples/debugprintfdemo/debugprintfdemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ int main()
{
SystemInit();

while( !DebugPrintfBufferFree() );

// Enable GPIOs
RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC;

Expand Down
2 changes: 1 addition & 1 deletion examples/debugprintfdemo/funconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// Though this should be on by default we can extra force it on.
#define FUNCONF_USE_DEBUGPRINTF 1
#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time.
//#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Optionally, wait for a very very long time on every printf.

#define CH32V003 1

Expand Down
41 changes: 25 additions & 16 deletions examples/template/.vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
{
"configurations": [
{
"name": "RISCV32EC",
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/../../ch32v003fun",
"${workspaceFolder}/../../extralibs",
"/usr/include/newlib" //why? the configurationProvider ought to find this
"${workspaceFolder}/../../ch32v003fun"
],
"defines": [
"CH32V003",
"__riscv",
"USE_SIGNALS",
"CH32V003FUN_BASE"
"defines": [],
"compilerPath": "/usr/bin/clang",
"cppStandard": "c++20",
"intelliSenseMode": "linux-clang-x64",
"compilerArgs": [
"-DCH32V003FUN_BASE"
],
"configurationProvider": "ms-vscode.makefile-tools"
},
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/../../ch32v003fun"
],
"defines": [],
"compilerPath": "riscv64-unknown-elf-gcc-10.1.0.exe",
"cppStandard": "c++20",
"compilerArgs": [
"-DCH32V003FUN_BASE"
],
"compilerPath": "/usr/bin/riscv64-unknown-elf-gcc",
"cStandard": "gnu11",
"cppStandard": "gnu++17",
"intelliSenseMode": "gcc-x86", //works. Someday, intellisense might get riscv modes
"compilerArgs": [],
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}
"version": 4,
"enableConfigurationSquiggles": true
}
34 changes: 10 additions & 24 deletions examples/template/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,33 @@
{
"configurations": [
{
"name": "cppdbg GDB Debug Target",
"name": "GDB Debug Target",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/template.elf",
"program": "debugprintfdemo.elf",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"deploySteps": [ // 'make ...gdbserver' doesn't seem to work here. The Makefile calls 'minichlink -baG'... Needs -aG. Easier to add minichlink as a seperate step below
{
"type": "shell", //isn't there some way to call a task from tasks.json?
"command": "make --directory=${workspaceFolder} -j 1 closechlink flash",
},
{
"type": "shell",
"command": "${workspaceFolder}/../../minichlink/minichlink -aG",
"continueOn": "gdbserver running"
},
],
"preLaunchTask": "run_flash_and_gdbserver",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true,
},
"ignoreFailures": true
}
],
"svdPath": "${workspaceFolder}/../../misc/CH32V003xx.svd", // extension 'Peripheral Viewer' by mcu-debug (cortex-debug)
"miDebuggerPath": "gdb-multiarch",
"miDebuggerServerAddress": "localhost:2000",
"logging": {
"engineLogging": false
},
"miDebuggerServerAddress": "127.0.0.1:2000"
},
{
"name": "Run Only (In Terminal)",
"type": "node",
"request": "launch",
"program": "",
"preLaunchTask": "run_flash_and_gdbserver",
}
]
}
"preLaunchTask": "run_flash_and_monitor",
}
]
}
6 changes: 3 additions & 3 deletions examples/template/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"makefile.launchConfigurations": [
{
"cwd": "",
"sbinaryPath": "template.elf",
"sbinaryPath": "debugprintfdemo.elf",
"binaryArgs": []
}
],
"editor.insertSpaces": false,
"editor.tabSize": 4,
"files.associations": {
"ch32v003fun.h": "c"
},
}
}
}
Loading

0 comments on commit ec36cfc

Please sign in to comment.