Build GD32 project with Platformio

Exactly, the builder script (spl.py in platform-ststm32/builder/frameworks/spl.py at develop · platformio/platform-ststm32 · GitHub) adds the whole \gd32\cmsis\variants\gd32f13 path to CPPPATH so it all gets compiled / assembled. Note that this startup file has a commented-out call to the libc array init functions (C++ constructor calls on startup), because that produces an error I haven’t quiet figured out how to solve yet…

There should be GD32F130C6T_FLASH_BACKUP.ld and GD32F130C6T_DEFAULT.ld after compilation. The auto-generated linker script is perfectly fine and the pre-provided one seemed very fishy to me. E.g.,

The _estack is the start value of the stack pointer (SP) and it should point to the end of RAM (stack grows downwards). However 0x20000000 + 4*1024 = 0x20001000, not 0x20000400… The autogenerated link file gets it right. Also a non-existing memory bank MEMORY_B1 of 0 Kilobytes was suspicious…

Hm first of all this sounds like a race condition or compiler optimization. But I checked and all the I2C related variables have been marked with volatile, so the variables i2c_nDABytes and i2c_status should be freshly read from memory every time. Otherwise it could again, like with systick.c do tricks regarding reading the variable only once and quick-exiting, before it could have been modified by the ISR.
However, I find

quiete suspicious because an empty loop with a local uint16_t k variable can be completely optimized away by the compiler (has no outside effect), but I think this is some needed intra-byte delay for I2C. But then please use a microsecond delay function from somewhere or force a volatile asm section with a NOP instruction that will not get optimized away.

for(k=0; k<500; k++) {
   //unoptimizable NOP loop, 500 times. 
   asm volatile ("nop");
}

How much delay is needed there?

Overall there seem to be some problems regarding different compiler optimization levels. What settings are you using for the Keil compiler?

You can also disable GCC optimizations by writing

build_unflags = -Os
build_flags = -O0

in the platformio.ini for optimization level 0. But then you need to disable some serial output again or use the slimmer “print raw string” function.