diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..6313b56
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
new file mode 100644
index 0000000..b8d7fd7
--- /dev/null
+++ b/.github/workflows/main.yaml
@@ -0,0 +1,25 @@
+on:
+ push:
+
+jobs:
+ build:
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: arm-none-eabi-gcc
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '10.3-2021.10'
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Make
+ run: make
+
+ - name: 'Upload Artifact'
+ uses: actions/upload-artifact@v3
+ with:
+ name: 'Flash Loader'
+ path: dp32-fl.elf
+
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..c28ee4b
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,32 @@
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ build:
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: arm-none-eabi-gcc
+ uses: carlosperate/arm-none-eabi-gcc-action@v1
+ with:
+ release: '10.3-2021.10'
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Make
+ run: make
+
+ - name: 'Upload Artifact'
+ uses: actions/upload-artifact@v3
+ with:
+ name: 'Flash Loader'
+ path: dp32-fl.elf
+
+ - name: 'Create Release'
+ uses: ncipollo/release-action@v1
+ with:
+ artifacts: "dp32-fl.elf,Devices.xml"
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6020452
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.d
+*.o
+*.elf
diff --git a/Devices.xml b/Devices.xml
new file mode 100644
index 0000000..050fd61
--- /dev/null
+++ b/Devices.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..31bf51a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+TARGET = dp32-fl
+
+OBJS = $(TARGET).o
+
+ifeq ($(OS),Windows_NT)
+TOP := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+else
+TOP := $(shell pwd)
+endif
+
+AS = arm-none-eabi-as
+CC = arm-none-eabi-gcc
+LD = arm-none-eabi-gcc
+OBJCOPY = arm-none-eabi-objcopy
+SIZE = arm-none-eabi-size
+
+ASFLAGS = -mcpu=cortex-m0
+CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD -fno-toplevel-reorder
+CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
+CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
+LDFLAGS = -mcpu=cortex-m0 -nostartfiles -Wl,-T,dp32-fl.ld -Wl,-x
+
+INC =
+LIBS =
+
+DEPS = $(OBJS:.o=.d)
+
+all: $(TARGET).elf
+ $(SIZE) $<
+
+$(TARGET).elf: $(OBJS)
+ $(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
+
+%.o: %.c | $(BSP_HEADERS)
+ $(CC) $(CFLAGS) $(INC) -c $< -o $@
+
+%.o: %.S
+ $(AS) $(ASFLAGS) $< -o $@
+
+-include $(DEPS)
+
+clean:
+ rm -f $(TARGET).elf $(OBJS) $(DEPS)
+
diff --git a/README.md b/README.md
index 281c5b8..553f87f 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,41 @@
-# dp32g030-flash-loader
\ No newline at end of file
+# Flash Loader for Segger JLink software to support the DP32G030
+
+This flash loader supports flashing to the DP32G030 as used in the [UV-K5](https://github.com/DualTachyon/uv-k5-firmware) class of radio transceivers.
+
+# Build
+
+```
+make
+```
+
+# Usage on Windows
+
+Create a folder:
+
+```
+md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices"
+md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon"
+md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030"
+copy Devices.xml "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030\"
+copy dp32-fl.elf "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030\"
+```
+
+For Linux, you'll have to figure out the paths, but should be a similar approach as Windows.
+
+# License
+
+Copyright 2023 Dual Tachyon
+https://github.com/DualTachyon
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/dp32-fl.c b/dp32-fl.c
new file mode 100644
index 0000000..a85c17c
--- /dev/null
+++ b/dp32-fl.c
@@ -0,0 +1,194 @@
+#include "flash.h"
+
+#define BLOCK_SIZE 512
+
+typedef struct {
+ uint32_t Size;
+ uint32_t Address;
+} SectorInfo_t;
+
+typedef struct {
+ uint16_t AlgoVer;
+ uint8_t Name[128];
+ uint16_t Type;
+ uint32_t BaseAddr;
+ uint32_t TotalSize;
+ uint32_t PageSize;
+ uint32_t Reserved;
+ uint8_t ErasedVal;
+ uint8_t Padding[3];
+ uint32_t TimeoutProg;
+ uint32_t TimeoutErase;
+ SectorInfo_t SectorInfo[2];
+} FlashDevice_t;
+
+extern const FlashDevice_t FlashDevice __attribute__((section(".constdata")));
+
+const FlashDevice_t FlashDevice = {
+ 0x0101,
+ "DP32G030 Internal Flash",
+ 1,
+ 0x00000000,
+ 0x0000F000,
+ 0x00000200,
+ 0x00000000,
+ 0xFF,
+ { 0x00, 0x00, 0x00},
+ 500,
+ 500,
+ {
+ { 0x00000200, 0x00000000 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ }
+};
+
+static void WaitNotBusy(void)
+{
+ while (1) {
+ if ((FLASH_ST & FLASH_ST_BUSY_MASK) == FLASH_ST_BUSY_BITS_READY) {
+ return;
+ }
+ }
+}
+
+static void WaitForEmpty(void)
+{
+ while (1) {
+ if ((FLASH_ST & FLASH_ST_PROG_BUF_EMPTY_MASK) == FLASH_ST_PROG_BUF_EMPTY_BITS_EMPTY) {
+ return;
+ }
+ }
+}
+
+static void FlashLock(void)
+{
+ FLASH_LOCK = FLASH_LOCK_LOCK_BITS_LOCK;
+}
+
+static void FlashUnlock(void)
+{
+ FLASH_UNLOCK = FLASH_UNLOCK_UNLOCK_BITS_UNLOCK;
+}
+
+static void FlashStart(void)
+{
+ FlashUnlock();
+
+ FLASH_START = FLASH_START_START_BITS_START;
+}
+
+static void FlashStop(void)
+{
+ FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_VALUE_READ_AHB;
+}
+
+static void FlashHalfSector(uint32_t Address, const uint8_t *pBuffer, uint32_t WordCount)
+{
+ const uint32_t *pWord = (const uint32_t *)pBuffer;
+ uint32_t i;
+
+ WaitNotBusy();
+
+ FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_BITS_PROGRAM;
+ FLASH_ADDR = Address >> 2;
+ FLASH_WDATA = *pWord++;
+
+ FlashStart();
+
+ for (i = 1; i < WordCount; i++) {
+ WaitForEmpty();
+ FLASH_WDATA = *pWord++;
+ }
+
+ WaitNotBusy();
+
+ FlashStop();
+ FlashLock();
+}
+
+// --------
+
+int Init(uint32_t Addr, uint32_t Freq, uint32_t Func) __attribute__((section("PrgCode")));
+int UnInit(uint32_t Func) __attribute__((section("PrgCode")));
+int EraseChip(void) __attribute__((section("PrgCode")));
+int EraseSector(uint32_t SectorAddr) __attribute__((section("PrgCode")));
+int ProgramPage(uint32_t DestAddr, uint32_t NumBytes, const uint8_t *pSrcBuff) __attribute__((section("PrgCode")));
+int CheckBlank(uint32_t Addr, uint32_t NumBytes, uint8_t BlankValue) __attribute__((section("PrgCode")));
+
+int Init(uint32_t Addr, uint32_t Freq, uint32_t Func)
+{
+ if (FLASH_MASK != 6) {
+ FLASH_MASK = 0;
+ WaitNotBusy();
+ FLASH_MASK = 6;
+ WaitNotBusy();
+ if (FLASH_MASK != 6) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int UnInit(uint32_t Func)
+{
+ // restore the MCU
+
+ return 0;
+}
+
+int EraseChip(void)
+{
+ uint16_t i;
+
+ for (i = 0; i < 0xF000; i += 512) {
+ int ret = EraseSector(i);
+
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int EraseSector(uint32_t SectorAddr)
+{
+
+ if (SectorAddr % 512 || SectorAddr >= 0xF000) {
+ return 1;
+ }
+
+ WaitNotBusy();
+
+ FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_BITS_ERASE;
+
+ FLASH_ADDR = SectorAddr >> 2;
+
+ FlashStart();
+ WaitNotBusy();
+ FlashStop();
+ FlashLock();
+
+ return 0;
+}
+
+
+int ProgramPage(uint32_t DestAddr, uint32_t NumBytes, const uint8_t *pBuffer)
+{
+ if (DestAddr % BLOCK_SIZE || DestAddr >= 0xF000 || NumBytes % BLOCK_SIZE || NumBytes > 0xF000 || (DestAddr + NumBytes) > 0xF000) {
+ return 1;
+ }
+
+ while (NumBytes >= BLOCK_SIZE) {
+ FlashHalfSector(DestAddr + 0x0000, pBuffer + 0x0000, BLOCK_SIZE / 4);
+ FlashHalfSector(DestAddr + 0x0100, pBuffer + 0x0100, BLOCK_SIZE / 4);
+ NumBytes -= BLOCK_SIZE;
+ pBuffer += BLOCK_SIZE;
+ }
+
+ FlashStop();
+ FlashLock();
+
+ return 0;
+}
diff --git a/dp32-fl.ld b/dp32-fl.ld
new file mode 100644
index 0000000..520a923
--- /dev/null
+++ b/dp32-fl.ld
@@ -0,0 +1,51 @@
+ENTRY(Init)
+
+MEMORY
+{
+ RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 1K
+}
+
+SECTIONS
+{
+ PrgCode :
+ {
+ . = ALIGN(4);
+ *(.PrgCode)
+ *(.PrgCode*)
+ *(.text)
+ *(.text*)
+ . = ALIGN(4);
+ } >RAM
+
+ PrgData :
+ {
+ . = ALIGN(4);
+ *(.PrgData)
+ *(.PrgData*)
+ *(.data)
+ *(.data*)
+ *(.rodata)
+ *(.rodata*)
+ _sbss = .;
+ *(.bss)
+ *(.bss*)
+ . = ALIGN(4);
+ } >RAM
+
+ DevDscr :
+ {
+ . = ALIGN(4);
+ *(.DevDscr)
+ *(.DevDscr*)
+ *(.constdata)
+ *(.constdata*)
+ . = ALIGN(4);
+ } >RAM
+
+ /DISCARD/ :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+}
diff --git a/flash.h b/flash.h
new file mode 100644
index 0000000..f17b3d0
--- /dev/null
+++ b/flash.h
@@ -0,0 +1,165 @@
+/* Copyright 2023 Dual Tachyon
+ * https://github.com/DualTachyon
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_DP32G030_FLASH_H
+#define HARDWARE_DP32G030_FLASH_H
+
+#if !defined(__ASSEMBLY__)
+#include
+#endif
+
+/* -------- FLASH -------- */
+#define FLASH_BASE_ADDR 0x4006F000U
+#define FLASH_BASE_SIZE 0x00000800U
+
+#define FLASH_CFG_ADDR (FLASH_BASE_ADDR + 0x0000U)
+#define FLASH_CFG (*(volatile uint32_t *)FLASH_CFG_ADDR)
+#define FLASH_CFG_READ_MD_SHIFT 0
+#define FLASH_CFG_READ_MD_WIDTH 1
+#define FLASH_CFG_READ_MD_MASK (((1U << FLASH_CFG_READ_MD_WIDTH) - 1U) << FLASH_CFG_READ_MD_SHIFT)
+#define FLASH_CFG_READ_MD_VALUE_1_CYCLE 0U
+#define FLASH_CFG_READ_MD_BITS_1_CYCLE (FLASH_CFG_READ_MD_VALUE_1_CYCLE << FLASH_CFG_READ_MD_SHIFT)
+#define FLASH_CFG_READ_MD_VALUE_2_CYCLE 1U
+#define FLASH_CFG_READ_MD_BITS_2_CYCLE (FLASH_CFG_READ_MD_VALUE_2_CYCLE << FLASH_CFG_READ_MD_SHIFT)
+
+#define FLASH_CFG_NVR_SEL_SHIFT 1
+#define FLASH_CFG_NVR_SEL_WIDTH 1
+#define FLASH_CFG_NVR_SEL_MASK (((1U << FLASH_CFG_NVR_SEL_WIDTH) - 1U) << FLASH_CFG_NVR_SEL_SHIFT)
+#define FLASH_CFG_NVR_SEL_VALUE_MAIN 0U
+#define FLASH_CFG_NVR_SEL_BITS_MAIN (FLASH_CFG_NVR_SEL_VALUE_MAIN << FLASH_CFG_NVR_SEL_SHIFT)
+#define FLASH_CFG_NVR_SEL_VALUE_NVR 1U
+#define FLASH_CFG_NVR_SEL_BITS_NVR (FLASH_CFG_NVR_SEL_VALUE_NVR << FLASH_CFG_NVR_SEL_SHIFT)
+
+#define FLASH_CFG_MODE_SHIFT 2
+#define FLASH_CFG_MODE_WIDTH 3
+#define FLASH_CFG_MODE_MASK (((1U << FLASH_CFG_MODE_WIDTH) - 1U) << FLASH_CFG_MODE_SHIFT)
+#define FLASH_CFG_MODE_VALUE_READ_AHB 0U
+#define FLASH_CFG_MODE_BITS_READ_AHB (FLASH_CFG_MODE_VALUE_READ_AHB << FLASH_CFG_MODE_SHIFT)
+#define FLASH_CFG_MODE_VALUE_PROGRAM 1U
+#define FLASH_CFG_MODE_BITS_PROGRAM (FLASH_CFG_MODE_VALUE_PROGRAM << FLASH_CFG_MODE_SHIFT)
+#define FLASH_CFG_MODE_VALUE_ERASE 2U
+#define FLASH_CFG_MODE_BITS_ERASE (FLASH_CFG_MODE_VALUE_ERASE << FLASH_CFG_MODE_SHIFT)
+#define FLASH_CFG_MODE_VALUE_READ_APB 5U
+#define FLASH_CFG_MODE_BITS_READ_APB (FLASH_CFG_MODE_VALUE_READ_APB << FLASH_CFG_MODE_SHIFT)
+
+#define FLASH_CFG_DEEP_PD_SHIFT 31
+#define FLASH_CFG_DEEP_PD_WIDTH 1
+#define FLASH_CFG_DEEP_PD_MASK (((1U << FLASH_CFG_DEEP_PD_WIDTH) - 1U) << FLASH_CFG_DEEP_PD_SHIFT)
+#define FLASH_CFG_DEEP_PD_VALUE_NORMAL 0U
+#define FLASH_CFG_DEEP_PD_BITS_NORMAL (FLASH_CFG_DEEP_PD_VALUE_NORMAL << FLASH_CFG_DEEP_PD_SHIFT)
+#define FLASH_CFG_DEEP_PD_VALUE_LOW_POWER 1U
+#define FLASH_CFG_DEEP_PD_BITS_LOW_POWER (FLASH_CFG_DEEP_PD_VALUE_LOW_POWER << FLASH_CFG_DEEP_PD_SHIFT)
+
+#define FLASH_ADDR_ADDR (FLASH_BASE_ADDR + 0x0004U)
+#define FLASH_ADDR (*(volatile uint32_t *)FLASH_ADDR_ADDR)
+#define FLASH_WDATA_ADDR (FLASH_BASE_ADDR + 0x0008U)
+#define FLASH_WDATA (*(volatile uint32_t *)FLASH_WDATA_ADDR)
+#define FLASH_RDATA_ADDR (FLASH_BASE_ADDR + 0x000CU)
+#define FLASH_RDATA (*(volatile uint32_t *)FLASH_RDATA_ADDR)
+
+#define FLASH_START_ADDR (FLASH_BASE_ADDR + 0x0010U)
+#define FLASH_START (*(volatile uint32_t *)FLASH_START_ADDR)
+#define FLASH_START_START_SHIFT 0
+#define FLASH_START_START_WIDTH 1
+#define FLASH_START_START_MASK (((1U << FLASH_START_START_WIDTH) - 1U) << FLASH_START_START_SHIFT)
+#define FLASH_START_START_VALUE_START 1U
+#define FLASH_START_START_BITS_START (FLASH_START_START_VALUE_START << FLASH_START_START_SHIFT)
+
+#define FLASH_ST_ADDR (FLASH_BASE_ADDR + 0x0014U)
+#define FLASH_ST (*(volatile uint32_t *)FLASH_ST_ADDR)
+#define FLASH_ST_INIT_BUSY_SHIFT 0
+#define FLASH_ST_INIT_BUSY_WIDTH 1
+#define FLASH_ST_INIT_BUSY_MASK (((1U << FLASH_ST_INIT_BUSY_WIDTH) - 1U) << FLASH_ST_INIT_BUSY_SHIFT)
+#define FLASH_ST_INIT_BUSY_VALUE_COMPLETE 0U
+#define FLASH_ST_INIT_BUSY_BITS_COMPLETE (FLASH_ST_INIT_BUSY_VALUE_COMPLETE << FLASH_ST_INIT_BUSY_SHIFT)
+#define FLASH_ST_INIT_BUSY_VALUE_BUSY 1U
+#define FLASH_ST_INIT_BUSY_BITS_BUSY (FLASH_ST_INIT_BUSY_VALUE_BUSY << FLASH_ST_INIT_BUSY_SHIFT)
+
+#define FLASH_ST_BUSY_SHIFT 1
+#define FLASH_ST_BUSY_WIDTH 1
+#define FLASH_ST_BUSY_MASK (((1U << FLASH_ST_BUSY_WIDTH) - 1U) << FLASH_ST_BUSY_SHIFT)
+#define FLASH_ST_BUSY_VALUE_READY 0U
+#define FLASH_ST_BUSY_BITS_READY (FLASH_ST_BUSY_VALUE_READY << FLASH_ST_BUSY_SHIFT)
+#define FLASH_ST_BUSY_VALUE_BUSY 1U
+#define FLASH_ST_BUSY_BITS_BUSY (FLASH_ST_BUSY_VALUE_BUSY << FLASH_ST_BUSY_SHIFT)
+
+#define FLASH_ST_PROG_BUF_EMPTY_SHIFT 2
+#define FLASH_ST_PROG_BUF_EMPTY_WIDTH 1
+#define FLASH_ST_PROG_BUF_EMPTY_MASK (((1U << FLASH_ST_PROG_BUF_EMPTY_WIDTH) - 1U) << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
+#define FLASH_ST_PROG_BUF_EMPTY_VALUE_NOT_EMPTY 0U
+#define FLASH_ST_PROG_BUF_EMPTY_BITS_NOT_EMPTY (FLASH_ST_PROG_BUF_EMPTY_VALUE_NOT_EMPTY << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
+#define FLASH_ST_PROG_BUF_EMPTY_VALUE_EMPTY 1U
+#define FLASH_ST_PROG_BUF_EMPTY_BITS_EMPTY (FLASH_ST_PROG_BUF_EMPTY_VALUE_EMPTY << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
+
+#define FLASH_LOCK_ADDR (FLASH_BASE_ADDR + 0x0018U)
+#define FLASH_LOCK (*(volatile uint32_t *)FLASH_LOCK_ADDR)
+#define FLASH_LOCK_LOCK_SHIFT 0
+#define FLASH_LOCK_LOCK_WIDTH 8
+#define FLASH_LOCK_LOCK_MASK (((1U << FLASH_LOCK_LOCK_WIDTH) - 1U) << FLASH_LOCK_LOCK_SHIFT)
+#define FLASH_LOCK_LOCK_VALUE_LOCK 85U
+#define FLASH_LOCK_LOCK_BITS_LOCK (FLASH_LOCK_LOCK_VALUE_LOCK << FLASH_LOCK_LOCK_SHIFT)
+
+#define FLASH_UNLOCK_ADDR (FLASH_BASE_ADDR + 0x001CU)
+#define FLASH_UNLOCK (*(volatile uint32_t *)FLASH_UNLOCK_ADDR)
+#define FLASH_UNLOCK_UNLOCK_SHIFT 0
+#define FLASH_UNLOCK_UNLOCK_WIDTH 8
+#define FLASH_UNLOCK_UNLOCK_MASK (((1U << FLASH_UNLOCK_UNLOCK_WIDTH) - 1U) << FLASH_UNLOCK_UNLOCK_SHIFT)
+#define FLASH_UNLOCK_UNLOCK_VALUE_UNLOCK 170U
+#define FLASH_UNLOCK_UNLOCK_BITS_UNLOCK (FLASH_UNLOCK_UNLOCK_VALUE_UNLOCK << FLASH_UNLOCK_UNLOCK_SHIFT)
+
+#define FLASH_MASK_ADDR (FLASH_BASE_ADDR + 0x0020U)
+#define FLASH_MASK (*(volatile uint32_t *)FLASH_MASK_ADDR)
+#define FLASH_MASK_SEL_SHIFT 0
+#define FLASH_MASK_SEL_WIDTH 2
+#define FLASH_MASK_SEL_MASK (((1U << FLASH_MASK_SEL_WIDTH) - 1U) << FLASH_MASK_SEL_SHIFT)
+#define FLASH_MASK_SEL_VALUE_NONE 0U
+#define FLASH_MASK_SEL_BITS_NONE (FLASH_MASK_SEL_VALUE_NONE << FLASH_MASK_SEL_SHIFT)
+#define FLASH_MASK_SEL_VALUE_2KB 1U
+#define FLASH_MASK_SEL_BITS_2KB (FLASH_MASK_SEL_VALUE_2KB << FLASH_MASK_SEL_SHIFT)
+#define FLASH_MASK_SEL_VALUE_4KB 2U
+#define FLASH_MASK_SEL_BITS_4KB (FLASH_MASK_SEL_VALUE_4KB << FLASH_MASK_SEL_SHIFT)
+#define FLASH_MASK_SEL_VALUE_8KB 3U
+#define FLASH_MASK_SEL_BITS_8KB (FLASH_MASK_SEL_VALUE_8KB << FLASH_MASK_SEL_SHIFT)
+
+#define FLASH_MASK_LOCK_SHIFT 2
+#define FLASH_MASK_LOCK_WIDTH 1
+#define FLASH_MASK_LOCK_MASK (((1U << FLASH_MASK_LOCK_WIDTH) - 1U) << FLASH_MASK_LOCK_SHIFT)
+#define FLASH_MASK_LOCK_VALUE_NOT_SET 0U
+#define FLASH_MASK_LOCK_BITS_NOT_SET (FLASH_MASK_LOCK_VALUE_NOT_SET << FLASH_MASK_LOCK_SHIFT)
+#define FLASH_MASK_LOCK_VALUE_SET 1U
+#define FLASH_MASK_LOCK_BITS_SET (FLASH_MASK_LOCK_VALUE_SET << FLASH_MASK_LOCK_SHIFT)
+
+#define FLASH_ERASETIME_ADDR (FLASH_BASE_ADDR + 0x0024U)
+#define FLASH_ERASETIME (*(volatile uint32_t *)FLASH_ERASETIME_ADDR)
+#define FLASH_ERASETIME_TERASE_SHIFT 0
+#define FLASH_ERASETIME_TERASE_WIDTH 19
+#define FLASH_ERASETIME_TERASE_MASK (((1U << FLASH_ERASETIME_TERASE_WIDTH) - 1U) << FLASH_ERASETIME_TERASE_SHIFT)
+#define FLASH_ERASETIME_TRCV_SHIFT 19
+#define FLASH_ERASETIME_TRCV_WIDTH 12
+#define FLASH_ERASETIME_TRCV_MASK (((1U << FLASH_ERASETIME_TRCV_WIDTH) - 1U) << FLASH_ERASETIME_TRCV_SHIFT)
+
+#define FLASH_PROGTIME_ADDR (FLASH_BASE_ADDR + 0x0028U)
+#define FLASH_PROGTIME (*(volatile uint32_t *)FLASH_PROGTIME_ADDR)
+#define FLASH_PROGTIME_TPROG_SHIFT 0
+#define FLASH_PROGTIME_TPROG_WIDTH 11
+#define FLASH_PROGTIME_TPROG_MASK (((1U << FLASH_PROGTIME_TPROG_WIDTH) - 1U) << FLASH_PROGTIME_TPROG_SHIFT)
+#define FLASH_PROGTIME_TPGS_SHIFT 11
+#define FLASH_PROGTIME_TPGS_WIDTH 11
+#define FLASH_PROGTIME_TPGS_MASK (((1U << FLASH_PROGTIME_TPGS_WIDTH) - 1U) << FLASH_PROGTIME_TPGS_SHIFT)
+
+
+#endif
+