Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.

Commit a2a21dd

Browse files
Dual TachyonDual Tachyon
authored andcommitted
Initial implementation.
1 parent da9ae75 commit a2a21dd

File tree

10 files changed

+562
-1
lines changed

10 files changed

+562
-1
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.github/workflows/main.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
on:
2+
push:
3+
4+
jobs:
5+
build:
6+
runs-on: ubuntu-22.04
7+
8+
steps:
9+
- name: arm-none-eabi-gcc
10+
uses: carlosperate/arm-none-eabi-gcc-action@v1
11+
with:
12+
release: '10.3-2021.10'
13+
14+
- name: Checkout
15+
uses: actions/checkout@v3
16+
17+
- name: Make
18+
run: make
19+
20+
- name: 'Upload Artifact'
21+
uses: actions/upload-artifact@v3
22+
with:
23+
name: 'Flash Loader'
24+
path: dp32-fl.elf
25+

.github/workflows/release.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
on:
2+
push:
3+
tags:
4+
- '*'
5+
6+
jobs:
7+
build:
8+
runs-on: ubuntu-22.04
9+
10+
steps:
11+
- name: arm-none-eabi-gcc
12+
uses: carlosperate/arm-none-eabi-gcc-action@v1
13+
with:
14+
release: '10.3-2021.10'
15+
16+
- name: Checkout
17+
uses: actions/checkout@v3
18+
19+
- name: Make
20+
run: make
21+
22+
- name: 'Upload Artifact'
23+
uses: actions/upload-artifact@v3
24+
with:
25+
name: 'Flash Loader'
26+
path: dp32-fl.elf
27+
28+
- name: 'Create Release'
29+
uses: ncipollo/release-action@v1
30+
with:
31+
artifacts: "dp32-fl.elf,Devices.xml"
32+

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.d
2+
*.o
3+
*.elf

Devices.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Database>
2+
<Device>
3+
<ChipInfo Vendor="DualTachyon" Name="DP32G030" WorkRAMAddr="0x20000000" WorkRAMSize="0x4000" Core="JLINK_CORE_CORTEX_M0" />
4+
<FlashBankInfo Name="Internal Code Flash" BaseAddr="0x00000000" MaxSize="0x0000F000" Loader="dp32-fl.elf" LoaderType="FLASH_ALGO_TYPE_OPEN" AlwaysPresent="1" />
5+
</Device>
6+
</Database>

Makefile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
TARGET = dp32-fl
2+
3+
OBJS = $(TARGET).o
4+
5+
ifeq ($(OS),Windows_NT)
6+
TOP := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
7+
else
8+
TOP := $(shell pwd)
9+
endif
10+
11+
AS = arm-none-eabi-as
12+
CC = arm-none-eabi-gcc
13+
LD = arm-none-eabi-gcc
14+
OBJCOPY = arm-none-eabi-objcopy
15+
SIZE = arm-none-eabi-size
16+
17+
ASFLAGS = -mcpu=cortex-m0
18+
CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD -fno-toplevel-reorder
19+
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
20+
CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
21+
LDFLAGS = -mcpu=cortex-m0 -nostartfiles -Wl,-T,dp32-fl.ld -Wl,-x
22+
23+
INC =
24+
LIBS =
25+
26+
DEPS = $(OBJS:.o=.d)
27+
28+
all: $(TARGET).elf
29+
$(SIZE) $<
30+
31+
$(TARGET).elf: $(OBJS)
32+
$(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
33+
34+
%.o: %.c | $(BSP_HEADERS)
35+
$(CC) $(CFLAGS) $(INC) -c $< -o $@
36+
37+
%.o: %.S
38+
$(AS) $(ASFLAGS) $< -o $@
39+
40+
-include $(DEPS)
41+
42+
clean:
43+
rm -f $(TARGET).elf $(OBJS) $(DEPS)
44+

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
# dp32g030-flash-loader
1+
# Flash Loader for Segger JLink software to support the DP32G030
2+
3+
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.
4+
5+
# Build
6+
7+
```
8+
make
9+
```
10+
11+
# Usage on Windows
12+
13+
Create a folder:
14+
15+
```
16+
md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices"
17+
md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon"
18+
md "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030"
19+
copy Devices.xml "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030\"
20+
copy dp32-fl.elf "%USERPROFILE%\AppData\Roaming\SEGGER\JLinkDevices\DualTachyon\DP32G030\"
21+
```
22+
23+
For Linux, you'll have to figure out the paths, but should be a similar approach as Windows.
24+
25+
# License
26+
27+
Copyright 2023 Dual Tachyon
28+
https://github.com/DualTachyon
29+
30+
Licensed under the Apache License, Version 2.0 (the "License");
31+
you may not use this file except in compliance with the License.
32+
You may obtain a copy of the License at
33+
34+
http://www.apache.org/licenses/LICENSE-2.0
35+
36+
Unless required by applicable law or agreed to in writing, software
37+
distributed under the License is distributed on an "AS IS" BASIS,
38+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
39+
See the License for the specific language governing permissions and
40+
limitations under the License.
41+

dp32-fl.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#include "flash.h"
2+
3+
#define BLOCK_SIZE 512
4+
5+
typedef struct {
6+
uint32_t Size;
7+
uint32_t Address;
8+
} SectorInfo_t;
9+
10+
typedef struct {
11+
uint16_t AlgoVer;
12+
uint8_t Name[128];
13+
uint16_t Type;
14+
uint32_t BaseAddr;
15+
uint32_t TotalSize;
16+
uint32_t PageSize;
17+
uint32_t Reserved;
18+
uint8_t ErasedVal;
19+
uint8_t Padding[3];
20+
uint32_t TimeoutProg;
21+
uint32_t TimeoutErase;
22+
SectorInfo_t SectorInfo[2];
23+
} FlashDevice_t;
24+
25+
extern const FlashDevice_t FlashDevice __attribute__((section(".constdata")));
26+
27+
const FlashDevice_t FlashDevice = {
28+
0x0101,
29+
"DP32G030 Internal Flash",
30+
1,
31+
0x00000000,
32+
0x0000F000,
33+
0x00000200,
34+
0x00000000,
35+
0xFF,
36+
{ 0x00, 0x00, 0x00},
37+
500,
38+
500,
39+
{
40+
{ 0x00000200, 0x00000000 },
41+
{ 0xFFFFFFFF, 0xFFFFFFFF },
42+
}
43+
};
44+
45+
static void WaitNotBusy(void)
46+
{
47+
while (1) {
48+
if ((FLASH_ST & FLASH_ST_BUSY_MASK) == FLASH_ST_BUSY_BITS_READY) {
49+
return;
50+
}
51+
}
52+
}
53+
54+
static void WaitForEmpty(void)
55+
{
56+
while (1) {
57+
if ((FLASH_ST & FLASH_ST_PROG_BUF_EMPTY_MASK) == FLASH_ST_PROG_BUF_EMPTY_BITS_EMPTY) {
58+
return;
59+
}
60+
}
61+
}
62+
63+
static void FlashLock(void)
64+
{
65+
FLASH_LOCK = FLASH_LOCK_LOCK_BITS_LOCK;
66+
}
67+
68+
static void FlashUnlock(void)
69+
{
70+
FLASH_UNLOCK = FLASH_UNLOCK_UNLOCK_BITS_UNLOCK;
71+
}
72+
73+
static void FlashStart(void)
74+
{
75+
FlashUnlock();
76+
77+
FLASH_START = FLASH_START_START_BITS_START;
78+
}
79+
80+
static void FlashStop(void)
81+
{
82+
FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_VALUE_READ_AHB;
83+
}
84+
85+
static void FlashHalfSector(uint32_t Address, const uint8_t *pBuffer, uint32_t WordCount)
86+
{
87+
const uint32_t *pWord = (const uint32_t *)pBuffer;
88+
uint32_t i;
89+
90+
WaitNotBusy();
91+
92+
FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_BITS_PROGRAM;
93+
FLASH_ADDR = Address >> 2;
94+
FLASH_WDATA = *pWord++;
95+
96+
FlashStart();
97+
98+
for (i = 1; i < WordCount; i++) {
99+
WaitForEmpty();
100+
FLASH_WDATA = *pWord++;
101+
}
102+
103+
WaitNotBusy();
104+
105+
FlashStop();
106+
FlashLock();
107+
}
108+
109+
// --------
110+
111+
int Init(uint32_t Addr, uint32_t Freq, uint32_t Func) __attribute__((section("PrgCode")));
112+
int UnInit(uint32_t Func) __attribute__((section("PrgCode")));
113+
int EraseChip(void) __attribute__((section("PrgCode")));
114+
int EraseSector(uint32_t SectorAddr) __attribute__((section("PrgCode")));
115+
int ProgramPage(uint32_t DestAddr, uint32_t NumBytes, const uint8_t *pSrcBuff) __attribute__((section("PrgCode")));
116+
int CheckBlank(uint32_t Addr, uint32_t NumBytes, uint8_t BlankValue) __attribute__((section("PrgCode")));
117+
118+
int Init(uint32_t Addr, uint32_t Freq, uint32_t Func)
119+
{
120+
if (FLASH_MASK != 6) {
121+
FLASH_MASK = 0;
122+
WaitNotBusy();
123+
FLASH_MASK = 6;
124+
WaitNotBusy();
125+
if (FLASH_MASK != 6) {
126+
return 1;
127+
}
128+
}
129+
130+
return 0;
131+
}
132+
133+
int UnInit(uint32_t Func)
134+
{
135+
// restore the MCU
136+
137+
return 0;
138+
}
139+
140+
int EraseChip(void)
141+
{
142+
uint16_t i;
143+
144+
for (i = 0; i < 0xF000; i += 512) {
145+
int ret = EraseSector(i);
146+
147+
if (ret) {
148+
return ret;
149+
}
150+
}
151+
152+
return 0;
153+
}
154+
155+
int EraseSector(uint32_t SectorAddr)
156+
{
157+
158+
if (SectorAddr % 512 || SectorAddr >= 0xF000) {
159+
return 1;
160+
}
161+
162+
WaitNotBusy();
163+
164+
FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | FLASH_CFG_MODE_BITS_ERASE;
165+
166+
FLASH_ADDR = SectorAddr >> 2;
167+
168+
FlashStart();
169+
WaitNotBusy();
170+
FlashStop();
171+
FlashLock();
172+
173+
return 0;
174+
}
175+
176+
177+
int ProgramPage(uint32_t DestAddr, uint32_t NumBytes, const uint8_t *pBuffer)
178+
{
179+
if (DestAddr % BLOCK_SIZE || DestAddr >= 0xF000 || NumBytes % BLOCK_SIZE || NumBytes > 0xF000 || (DestAddr + NumBytes) > 0xF000) {
180+
return 1;
181+
}
182+
183+
while (NumBytes >= BLOCK_SIZE) {
184+
FlashHalfSector(DestAddr + 0x0000, pBuffer + 0x0000, BLOCK_SIZE / 4);
185+
FlashHalfSector(DestAddr + 0x0100, pBuffer + 0x0100, BLOCK_SIZE / 4);
186+
NumBytes -= BLOCK_SIZE;
187+
pBuffer += BLOCK_SIZE;
188+
}
189+
190+
FlashStop();
191+
FlashLock();
192+
193+
return 0;
194+
}

0 commit comments

Comments
 (0)