-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathv003_flash.c
177 lines (151 loc) · 4.3 KB
/
v003_flash.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "v003_flash.h"
#include "ch32v003fun.h"
#include <stdio.h>
int flash_unlock(bool option_bytes, bool bootloader_bytes) {
Delay_Ms(100);
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;
// Unlocking option bytes.
if (option_bytes) {
FLASH->OBKEYR = 0x45670123;
FLASH->OBKEYR = 0xCDEF89AB;
}
// Unlocking BOOT area
if (bootloader_bytes) {
FLASH->BOOT_MODEKEYR = 0x45670123;
FLASH->BOOT_MODEKEYR = 0xCDEF89AB;
}
// Unlocking 64B page fast erase/write
FLASH->MODEKEYR = 0x45670123;
FLASH->MODEKEYR = 0xCDEF89AB;
#ifdef DEBUG_FLASH
printf( "FLASH->CTLR = %08lx\n", FLASH->CTLR );
#endif
if (FLASH->CTLR & 0x8080) {
#ifdef DEBUG_FLASH
printf( "Flash still locked\n" );
#endif
return -1;
}
return 0;
}
void flash_lock() {
FLASH->CTLR = CR_LOCK_Set;
}
int flash_erase(uint32_t* addr) {
int ret = 0;
if (FLASH->CTLR & 0x8080) {
ret = -1;
#ifdef DEBUG_FLASH
printf("Flash is locked\n");
#endif
} else {
FLASH->CTLR = CR_PAGE_ER;
FLASH->ADDR = (intptr_t)addr;
FLASH->CTLR = CR_STRT_Set | CR_PAGE_ER;
while(FLASH->STATR & FLASH_STATR_BSY); // Takes about 3ms.
#ifdef DEBUG_FLASH
printf("Erase complete\n");
#endif
if(addr[0] != 0xffffffff) {
#ifdef DBUG_FLASH
printf("Error: Flash general erasure failed\n");
#endif
ret = -2;
}
}
return ret;
}
int flash_erase_bulk(uint32_t* addr, uint32_t len) {
int ret = 0;
for (int i = 0; i < len; i++) {
ret = flash_erase(addr + (16*i));
if (ret) break;
}
return ret;
}
int flash_write(uint8_t* addr, uint8_t* data, uint32_t len, bool erase) {
if (!len) return -3;
if (len > 64) len = 64;
int ret = 0;
if (FLASH->CTLR & 0x8080) {
ret = -4;
#ifdef DEBUG_FLASH
printf("Flash is locked\n");
#endif
} else {
uint8_t buffer[64];
uint32_t* address = (uint32_t*)addr;
// uint32_t* data_ptr = (uint32_t*)data;
if (!(((intptr_t)addr & 63) == 0 && (len & 63) == 0)) {
// printf("doing stuff... %08x-%d %d-%d\n", (intptr_t)addr, ((intptr_t)addr & 63), len, (len & 63));
address = (uint32_t*)(((uintptr_t)addr / 64) * 64);
uint8_t diff = (intptr_t)addr - (intptr_t)address;
for (int n = 0; n < 64; n++) {
if (diff > n) buffer[n] = address[n];
else if ((len + diff) > n) buffer[n] = data[n];
else buffer[n] = addr[n - diff];
}
// data_ptr = (uint32_t*)buffer;
data = (uint32_t*)buffer;
}
if (erase) ret = flash_erase(address);
if (ret) return ret;
// Clear buffer and prep for flashing.
FLASH->CTLR = CR_PAGE_PG; // synonym of FTPG.
FLASH->CTLR = CR_BUF_RST | CR_PAGE_PG;
FLASH->ADDR = (intptr_t)address; // This can actually happen about anywhere toward the end here.
// Note: It takes about 6 clock cycles for this to finish.
while( FLASH->STATR & FLASH_STATR_BSY ); // No real need for this.
int i;
for (i = 0; i < 16; i++) {
address[i] = *((uint32_t*) data+i); //Write to the memory
// address[i] = data_ptr[i]; //Write to the memory
FLASH->CTLR = CR_PAGE_PG | FLASH_CTLR_BUF_LOAD; // Load the buffer.
while(FLASH->STATR & FLASH_STATR_BSY); // Only needed if running from RAM.
}
// Actually write the flash out. (Takes about 3ms)
FLASH->CTLR = CR_PAGE_PG|CR_STRT_Set;
// Wait until it finished
while(FLASH->STATR & FLASH_STATR_BSY);
#ifdef DEBUG_FLASH
printf("FLASH->STATR = %08lx\n", FLASH->STATR);
printf("Memory at: %08lx: %08lx %08lx\n", (uint32_t)addr, addr[0], addr[1]);
Delay_Ms(10);
#endif
#ifdef PRINT_PROGRESS
printf(".");
Delay_Ms(10);
#endif
if (addr[0] != data[0]) {
#ifdef DEBUG_FLASH
printf("Write error at addr: 0x%08;x\n", (uint32_t)addr);
for (int i = 0; i < 16; i++) {
printf("Data: %08lx Flash: %08lx\n", data[i], addr[i]);
}
Delay_Ms(10);
#endif
ret = -5;
}
}
return ret;
}
int flash_write_bulk(uint8_t* addr, uint8_t* data, uint32_t len, bool erase) {
int ret = 0;
int left = len;
if (len <= 64) {
ret = flash_write(addr, data, len, erase);
} else {
while (left > 0) {
ret = flash_write(addr + (len - left), data + (len - left), left, erase);
if (ret) break;
left -= 64;
}
}
if (ret && ret > -3) {
printf("\nError erasing block: %lu\n", len - left);
} else if (ret) {
printf("\nError writing block: %lu\n", len - left);
}
return ret;
}