From 71a9bfa4c1a34d746394d986bae1b0306523eb8a Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Sun, 12 Mar 2023 23:10:08 -0400
Subject: [PATCH] Add demo showing how to use optionbytes.

---
 examples/optionbytes/Makefile      |  55 +++++++++++
 examples/optionbytes/optionbytes.c | 147 +++++++++++++++++++++++++++++
 2 files changed, 202 insertions(+)
 create mode 100644 examples/optionbytes/Makefile
 create mode 100644 examples/optionbytes/optionbytes.c

diff --git a/examples/optionbytes/Makefile b/examples/optionbytes/Makefile
new file mode 100644
index 0000000..967b1fb
--- /dev/null
+++ b/examples/optionbytes/Makefile
@@ -0,0 +1,55 @@
+TARGET:=optionbytes
+
+all : flash
+
+PREFIX:=riscv64-unknown-elf
+
+GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User
+
+EVT:=../../ch32v003evt
+
+MINICHLINK:=../../minichlink
+
+ifeq ($(OS),Windows_NT)
+# On Windows, all the major RISC-V GCC installs are missing the -ec libgcc.
+LIB_GCC=../../misc/libgcc.a
+else
+LIB_GCC=-lgcc
+endif
+
+CH32V003FUN:=../../ch32v003fun
+
+CFLAGS:= \
+	-g -Os -flto -ffunction-sections \
+	-static-libgcc $(LIB_GCC) \
+	-march=rv32ec \
+	-mabi=ilp32e \
+	-I/usr/include/newlib \
+	-I$(CH32V003FUN) \
+	-nostdlib \
+	-I. -DTINYVECTOR
+
+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
+	$(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/optionbytes/optionbytes.c b/examples/optionbytes/optionbytes.c
new file mode 100644
index 0000000..25aaf5c
--- /dev/null
+++ b/examples/optionbytes/optionbytes.c
@@ -0,0 +1,147 @@
+// Really basic self-contained demo for the ch32v003
+// Doesn't rely on any of the weird HAL stuff from CH
+// Final executable is ~1/4th the size.
+
+// Could be defined here, or in the processor defines.
+#define SYSTEM_CORE_CLOCK 48000000
+
+#include "ch32v003fun.h"
+#include <stdio.h>
+
+uint32_t count;
+
+int FLASH_WaitForLastOperation(uint32_t Timeout);
+
+int main()
+{
+	SystemInit48HSI();
+	SetupDebugPrintf();
+
+	FLASH->OBKEYR = FLASH_KEY1;
+	FLASH->OBKEYR = FLASH_KEY2;
+	FLASH->KEYR = FLASH_KEY1;
+	FLASH->KEYR = FLASH_KEY2;
+	FLASH->MODEKEYR = FLASH_KEY1;
+	FLASH->MODEKEYR = FLASH_KEY2;
+
+	printf( "Option bytes started as:%04x\n", OB->USER );
+
+	uint16_t rdptmp = RDP_Key;
+
+
+	int status = FLASH_WaitForLastOperation(EraseTimeout);
+	if(status == FLASH_COMPLETE)
+	{
+		FLASH->OBKEYR = FLASH_KEY1;
+		FLASH->OBKEYR = FLASH_KEY2;
+
+		FLASH->CTLR |= CR_OPTER_Set;
+		FLASH->CTLR |= CR_STRT_Set;
+		status = FLASH_WaitForLastOperation(EraseTimeout);
+
+		if(status == FLASH_COMPLETE)
+		{
+			FLASH->CTLR &= CR_OPTER_Reset;
+			FLASH->CTLR |= CR_OPTPG_Set;
+			OB->RDPR = (uint16_t)rdptmp;
+			status = FLASH_WaitForLastOperation(ProgramTimeout);
+
+			if(status != FLASH_TIMEOUT)
+			{
+				FLASH->CTLR &= CR_OPTPG_Reset;
+			}
+		}
+		else
+		{
+			if(status != FLASH_TIMEOUT)
+			{
+				FLASH->CTLR &= CR_OPTPG_Reset;
+			}
+		}
+	}
+
+
+	printf( "After Clear:%04x\n", OB->USER );
+/* Notes from flash document:
+ * @param   OB_IWDG - Selects the IWDG mode
+ *            OB_IWDG_SW - Software IWDG selected
+ *            OB_IWDG_HW - Hardware IWDG selected
+ *          OB_STOP - Reset event when entering STOP mode.
+ *            OB_STOP_NoRST - No reset generated when entering in STOP
+ *            OB_STOP_RST - Reset generated when entering in STOP
+ *          OB_STDBY - Reset event when entering Standby mode.
+ *            OB_STDBY_NoRST - No reset generated when entering in STANDBY
+ *            OB_STDBY_RST - Reset generated when entering in STANDBY
+ *          OB_RST - Selects the reset IO mode and Ignore delay time
+ *            OB_RST_NoEN - Reset IO disable (PD7)
+ *            OB_RST_EN_DT12ms - Reset IO enable (PD7) and  Ignore delay time 12ms
+ *            OB_RST_EN_DT1ms - Reset IO enable (PD7) and  Ignore delay time 1ms
+ *            OB_RST_EN_DT128ms - Reset IO enable (PD7) and  Ignore delay time 128ms
+*/
+	uint16_t OB_IWDG = OB_STOP_NoRST;
+	uint16_t OB_STOP = OB_IWDG_SW;
+	uint16_t OB_STDBY = OB_STDBY_NoRST;
+	uint16_t OB_RST = OB_RST_EN_DT1ms;
+
+    FLASH->OBKEYR = FLASH_KEY1;
+    FLASH->OBKEYR = FLASH_KEY2;
+    status = FLASH_WaitForLastOperation(10000);
+
+    if(status == FLASH_COMPLETE)
+    {
+        FLASH->CTLR |= CR_OPTPG_Set;
+        OB->USER = OB_IWDG | (uint16_t)(OB_STOP | (uint16_t)(OB_STDBY | (uint16_t)(OB_RST | (uint16_t)0xE0)));
+
+        status = FLASH_WaitForLastOperation(10000);
+        if(status != FLASH_TIMEOUT)
+        {
+            FLASH->CTLR &= CR_OPTPG_Reset;
+        }
+    }
+
+	printf( "After Write:%04x\n", OB->USER );
+
+	while(1);
+}
+
+
+int FLASH_GetBank1Status(void)
+{
+	int flashstatus = FLASH_COMPLETE;
+
+	if((FLASH->STATR & FLASH_FLAG_BANK1_BSY) == FLASH_FLAG_BSY)
+	{
+		flashstatus = FLASH_BUSY;
+	}
+	else
+	{
+		if((FLASH->STATR & FLASH_FLAG_BANK1_WRPRTERR) != 0)
+		{
+			flashstatus = FLASH_ERROR_WRP;
+		}
+		else
+		{
+			flashstatus = FLASH_COMPLETE;
+		}
+	}
+	return flashstatus;
+}
+
+
+int FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+	int status = FLASH_COMPLETE;
+
+	status = FLASH_GetBank1Status();
+	while((status == FLASH_BUSY) && (Timeout != 0x00))
+	{
+		status = FLASH_GetBank1Status();
+		Timeout--;
+	}
+	if(Timeout == 0x00)
+	{
+		status = FLASH_TIMEOUT;
+	}
+	return status;
+}
+
-- 
GitLab