Skip to content
Snippets Groups Projects
Commit 16a7a47a authored by cnlohr's avatar cnlohr
Browse files

* Add self-modifying code example.

 * Add ability to wait for debugger to attach
parent ca2901c1
No related branches found
No related tags found
No related merge requests found
......@@ -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 )
{
......
......@@ -4851,6 +4851,9 @@ void SetupUART( int uartBRR );
void SetupDebugPrintf();
void WaitForDebuggerToAttach();
#ifdef __cplusplus
};
#endif
......
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
/* 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(;;);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment