From 16a7a47a31f07926475cb6b7fadbd07b5ce13a4d Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Tue, 14 Mar 2023 07:21:17 -0400 Subject: [PATCH] * Add self-modifying code example. * Add ability to wait for debugger to attach --- ch32v003fun/ch32v003fun.c | 6 ++ ch32v003fun/ch32v003fun.h | 3 + examples/self_modify_code/Makefile | 46 +++++++++++++ examples/self_modify_code/self_modify_code.c | 71 ++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 examples/self_modify_code/Makefile create mode 100644 examples/self_modify_code/self_modify_code.c diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index a97d1f8..72f14f2 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -896,6 +896,7 @@ int _write(int fd, const char *buf, int size) while( ((*DMDATA0) & 0x80) ) if( timeout-- == 0 ) return place; + timeout = 160000; uint32_t d; int t = 3; @@ -925,8 +926,13 @@ void SetupDebugPrintf() { // Clear out the sending flag. *DMDATA1 = 0x0; + *DMDATA0 = 0x80; } +void WaitForDebuggerToAttach() +{ + while( ((*DMDATA0) & 0x80) ); +} void DelaySysTick( uint32_t n ) { diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 3115d7c..34ee9b1 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -4851,6 +4851,9 @@ void SetupUART( int uartBRR ); void SetupDebugPrintf(); +void WaitForDebuggerToAttach(); + + #ifdef __cplusplus }; #endif diff --git a/examples/self_modify_code/Makefile b/examples/self_modify_code/Makefile new file mode 100644 index 0000000..ebe3d0b --- /dev/null +++ b/examples/self_modify_code/Makefile @@ -0,0 +1,46 @@ +TARGET:=self_modify_code + +all : flash + +PREFIX:=riscv64-unknown-elf + +GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User + +CH32V003FUN:=../../ch32v003fun +MINICHLINK:=../../minichlink + +CFLAGS:= \ + -g -Os -flto -ffunction-sections \ + -static-libgcc -lgcc \ + -march=rv32ec \ + -mabi=ilp32e \ + -I/usr/include/newlib \ + -I$(CH32V003FUN) \ + -nostdlib \ + -I. + +LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections + +SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c + +$(TARGET).elf : $(SYSTEM_C) $(TARGET).c + $(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + +$(TARGET).bin : $(TARGET).elf + $(PREFIX)-size $^ + $(PREFIX)-objdump -S $^ > $(TARGET).lst + $(PREFIX)-objdump -t $^ > $(TARGET).map + $(PREFIX)-objcopy -O binary $< $(TARGET).bin + $(PREFIX)-objcopy -O ihex $< $(TARGET).hex + +flash : $(TARGET).bin + make -C $(MINICHLINK) all + $(MINICHLINK)/minichlink -w $< flash -b + +monitor : flash + $(MINICHLINK)/minichlink -T + + +clean : + rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex + diff --git a/examples/self_modify_code/self_modify_code.c b/examples/self_modify_code/self_modify_code.c new file mode 100644 index 0000000..40f0940 --- /dev/null +++ b/examples/self_modify_code/self_modify_code.c @@ -0,0 +1,71 @@ +/* Small example showing how to use the SWIO programming pin to + do printf through the debug interface */ + +#define SYSTEM_CORE_CLOCK 24000000 +#include "ch32v003fun.h" +#include <stdio.h> + +uint32_t count; + + + +uint32_t ReadCSRSelfModify( uint16_t whichcsr ) __attribute__(( section(".data"))) __attribute__((noinline)); +uint32_t ReadCSRSelfModify( uint16_t whichcsr ) +{ + uint32_t ret; + + // Tricky: GCC will make this variable "point to" the opcode + // of the csrr instruction below. + volatile extern uint32_t readCSRLabel; + + // We have to put this here to "force" the compiler to order the + // instructions in this way. Otherwise, the compiler will try + // to optimize the code and inline the assembly int something where + // our global handle into assembly code becomes meaningless. + asm volatile( "nop" ); + + // 000026f3 is csrrs a3, 0x000, x0; So, we modify it, placing the + // CSR we want to read in the top 12 bits of the instruction. + + readCSRLabel = 0x000026f3 | (whichcsr << 20); + + // The actual assembly block inserted into the C function. This + // defines the local label, globally, so the linker will be able to + // pick it up. We also need to used a fixed register, a3, so we + // can know what opcode we want to use, then we can let C tell us + // what register it would like the value in. + // + // The constraints are "ret" is a "write" register, and register a3 + // is going to be clobbered by the assembly code. + asm volatile( + ".global readCSRLabel \n" + "readCSRLabel: \n" + " csrrs a3, 0x000, x0 \n" + " addi %[ret], a3, 0 \n" + : [ret]"=r"(ret) : : "a3" ); + + return ret; +} + + +int main() +{ + SystemInit48HSI(); + SetupDebugPrintf(); + + WaitForDebuggerToAttach(); + + // Enable GPIOs + RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC; + puts( "Print all non-zero CSRs:" ); + int i; + for( i = 0x000; i < 0x1000; i++ ) + { + uint32_t rv = ReadCSRSelfModify( i ); + if( rv ) + printf( "%03x = %08x\n", i, rv ); + } + printf( "Done\n" ); + for(;;); +} + -- GitLab