1
2
3
8
9
10
11
12
13
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
35
44
45
46
47
48
49
50
51
52
53
54
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
88
89
90
91
92
93
94
95
96
97
98
99
100
101
106
107
108
109
110
111
112
113
114
115
116
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
178
183
184
185
186
187
188
189
190
191
192
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
235
236
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
282
283
284
285
286
287
288
289
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
323
324
325
326
327
331
332
334
341
342
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/* ... */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include <helper/binarybuffer.h>
#include <helper/time_support.h>
#include <target/algorithm.h>
#include <target/arm.h>
5 includes
static int aduc702x_build_sector_list(struct flash_bank *bank);
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
static int aduc702x_set_write_enable(struct target *target, int enable);
#define ADUC702X_FLASH 0xfffff800
#define ADUC702X_FLASH_FEESTA (0*4)
#define ADUC702X_FLASH_FEEMOD (1*4)
#define ADUC702X_FLASH_FEECON (2*4)
#define ADUC702X_FLASH_FEEDAT (3*4)
#define ADUC702X_FLASH_FEEADR (4*4)
#define ADUC702X_FLASH_FEESIGN (5*4)
#define ADUC702X_FLASH_FEEPRO (6*4)
#define ADUC702X_FLASH_FEEHIDE (7*4)
9 defines
/* ... */
FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
{
bank->base = 0x80000;
bank->size = 0xF800;
aduc702x_build_sector_list(bank);
return ERROR_OK;
}{ ... }
static int aduc702x_build_sector_list(struct flash_bank *bank)
{
uint32_t offset = 0;
bank->num_sectors = bank->size / 512;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (unsigned int i = 0; i < bank->num_sectors; ++i) {
bank->sectors[i].offset = offset;
bank->sectors[i].size = 512;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}for (unsigned int i = 0; i < bank->num_sectors; ++i) { ... }
return ERROR_OK;
}{ ... }
static int aduc702x_erase(struct flash_bank *bank, unsigned int first,
unsigned int last)
{
int x;
int count;
struct target *target = bank->target;
aduc702x_set_write_enable(target, 1);
if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
LOG_DEBUG("performing mass erase.");
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEDAT, 0x3cff);
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, 0xffc3);
target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x06);
if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
LOG_ERROR("mass erase failed");
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED;
}if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) { ... }
LOG_DEBUG("mass erase successful.");
return ERROR_OK;
}if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) { ... } else {
unsigned long adr;
count = last - first + 1;
for (x = 0; x < count; ++x) {
adr = bank->base + ((first + x) * 512);
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, adr);
target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x05);
if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_SECTOR_NOT_ERASED;
}if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) { ... }
LOG_DEBUG("erased sector at address 0x%08lX", adr);
}for (x = 0; x < count; ++x) { ... }
}else { ... }
aduc702x_set_write_enable(target, 0);
return ERROR_OK;
}{ ... }
/* ... */
static int aduc702x_write_block(struct flash_bank *bank,
const uint8_t *buffer,
uint32_t offset,
uint32_t count)
{
struct target *target = bank->target;
uint32_t buffer_size = 7000;
struct working_area *write_algorithm;
struct working_area *source;
uint32_t address = bank->base + offset;
struct reg_param reg_params[6];
struct arm_algorithm arm_algo;
int retval = ERROR_OK;
if (((count%2) != 0) || ((offset%2) != 0)) {
LOG_ERROR("write block must be multiple of two bytes in offset & length");
return ERROR_FAIL;
}if (((count%2) != 0) || ((offset%2) != 0)) { ... }
/* ... */
static const uint32_t aduc702x_flash_write_code[] = {
0xe3a05008,
0xe5845004,
0xe3a06002,
0xe1c421b0,
0xe0d050b2,
0xe1c450bc,
0xe5c46008,
0xe1d430b0,
0xe3130004,
0x1afffffc,
0xe2822002,
0xe2511001,
0x0a000001,
0xe3130001,
0x1afffff3,
0xeafffffe
...};
if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code), &write_algorithm) != ERROR_OK) { ... }
uint8_t code[sizeof(aduc702x_flash_write_code)];
target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code),
aduc702x_flash_write_code);
retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
if (retval != ERROR_OK)
return retval;
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
if (buffer_size <= 256) {
/* ... */
target_free_working_area(target, write_algorithm);
LOG_WARNING("no large enough working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}if (buffer_size <= 256) { ... }
}while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { ... }
arm_algo.common_magic = ARM_COMMON_MAGIC;
arm_algo.core_mode = ARM_MODE_SVC;
arm_algo.core_state = ARM_STATE_ARM;
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
init_reg_param(®_params[3], "r3", 32, PARAM_IN);
init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
while (count > 0) {
uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
retval = target_write_buffer(target, source->address, thisrun_count, buffer);
if (retval != ERROR_OK)
break;
buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
buf_set_u32(reg_params[2].value, 0, 32, address);
buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
retval = target_run_algorithm(target, 0, NULL, 5,
reg_params, write_algorithm->address,
write_algorithm->address +
sizeof(aduc702x_flash_write_code) - 4,
10000, &arm_algo);
if (retval != ERROR_OK) {
LOG_ERROR("error executing aduc702x flash write algorithm");
break;
}if (retval != ERROR_OK) { ... }
if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
LOG_ERROR("aduc702x detected error writing flash");
retval = ERROR_FAIL;
break;
}if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) { ... }
buffer += thisrun_count;
address += thisrun_count;
count -= thisrun_count;
}while (count > 0) { ... }
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);
destroy_reg_param(®_params[2]);
destroy_reg_param(®_params[3]);
destroy_reg_param(®_params[4]);
return retval;
}{ ... }
/* ... */
static int aduc702x_write_single(struct flash_bank *bank,
const uint8_t *buffer,
uint32_t offset,
uint32_t count)
{
uint32_t x;
uint8_t b;
struct target *target = bank->target;
aduc702x_set_write_enable(target, 1);
for (x = 0; x < count; x += 2) {
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, offset + x);
if ((x + 1) == count) {
target_read_u8(target, offset + x + 1, &b);
}if ((x + 1) == count) { ... } else
b = buffer[x + 1];
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEDAT, buffer[x] | (b << 8));
target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x02);
if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
LOG_ERROR("single write failed for address 0x%08lX",
(unsigned long)(offset + x));
aduc702x_set_write_enable(target, 0);
return ERROR_FLASH_OPERATION_FAILED;
}if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) { ... }
}for (x = 0; x < count; x += 2) { ... }
LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
aduc702x_set_write_enable(target, 0);
return ERROR_OK;
}{ ... }
static int aduc702x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
int retval;
retval = aduc702x_write_block(bank, buffer, offset, count);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* ... */
LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
retval = aduc702x_write_single(bank, buffer, offset, count);
if (retval != ERROR_OK) {
LOG_ERROR("slow write failed");
return ERROR_FLASH_OPERATION_FAILED;
}if (retval != ERROR_OK) { ... }
}if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { ... }
}if (retval != ERROR_OK) { ... }
return retval;
}{ ... }
static int aduc702x_probe(struct flash_bank *bank)
{
return ERROR_OK;
}{ ... }
/* ... */
static int aduc702x_set_write_enable(struct target *target, int enable)
{
target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEMOD, enable ? 8 : 0);
return ERROR_OK;
}{ ... }
/* ... */
static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms)
{
uint8_t v = 4;
int64_t endtime = timeval_ms() + timeout_ms;
while (1) {
target_read_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEESTA, &v);
if ((v & 4) == 0)
break;
alive_sleep(1);
if (timeval_ms() >= endtime)
break;
}while (1) { ... }
if (v & 2)
return ERROR_FAIL;
else if ((v & 3) == 0)
return ERROR_FAIL;
else
return ERROR_OK;
}{ ... }
const struct flash_driver aduc702x_flash = {
.name = "aduc702x",
.flash_bank_command = aduc702x_flash_bank_command,
.erase = aduc702x_erase,
.write = aduc702x_write,
.read = default_flash_read,
.probe = aduc702x_probe,
.auto_probe = aduc702x_probe,
.erase_check = default_flash_blank_check,
...};