1 /***************************************************************************
2 * Copyright (C) 2015 by Ivan Buliev *
3 * i.buliev@mikrosistemi.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
19 /***************************************************************************
20 * This version for ADuCM360 is largely based on the following flash *
23 * Copyright (C) 2008 by Kevin McGuire *
24 * Copyright (C) 2008 by Marcel Wijlaars *
25 * Copyright (C) 2009 by Michael Ashton *
28 * Copyright (C) 2005 by Dominic Rath *
29 * Dominic.Rath@gmx.de *
31 * Copyright (C) 2008 by Spencer Oliver *
32 * spen@spen-soft.co.uk *
34 * Copyright (C) 2011 by Andreas Fritiofson *
35 * andreas.fritiofson@gmail.com *
36 ***************************************************************************/
43 #include <helper/binarybuffer.h>
44 #include <helper/time_support.h>
45 #include <target/algorithm.h>
46 #include <target/armv7m.h>
48 static int aducm360_build_sector_list(struct flash_bank *bank);
49 static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms);
50 static int aducm360_set_write_enable(struct target *target, int enable);
52 #define ADUCM360_FLASH_BASE 0x40002800
53 #define ADUCM360_FLASH_FEESTA 0x0000
54 #define ADUCM360_FLASH_FEECON0 0x0004
55 #define ADUCM360_FLASH_FEECMD 0x0008
56 #define ADUCM360_FLASH_FEEADR0L 0x0010
57 #define ADUCM360_FLASH_FEEADR0H 0x0014
58 #define ADUCM360_FLASH_FEEADR1L 0x0018
59 #define ADUCM360_FLASH_FEEADR1H 0x001C
60 #define ADUCM360_FLASH_FEEKEY 0x0020
61 #define ADUCM360_FLASH_FEEPROL 0x0028
62 #define ADUCM360_FLASH_FEEPROH 0x002C
63 #define ADUCM360_FLASH_FEESIGL 0x0030
64 #define ADUCM360_FLASH_FEESIGH 0x0034
65 #define ADUCM360_FLASH_FEECON1 0x0038
66 #define ADUCM360_FLASH_FEEADRAL 0x0048
67 #define ADUCM360_FLASH_FEEADRAH 0x004C
68 #define ADUCM360_FLASH_FEEAEN0 0x0078
69 #define ADUCM360_FLASH_FEEAEN1 0x007C
70 #define ADUCM360_FLASH_FEEAEN2 0x0080
72 /* flash bank aducm360 0 0 0 0 <target#> */
73 FLASH_BANK_COMMAND_HANDLER(aducm360_flash_bank_command)
75 bank->base = 0x00000000;
76 bank->size = 0x00020000;
78 aducm360_build_sector_list(bank);
83 #define FLASH_SECTOR_SIZE 512
85 /* ----------------------------------------------------------------------- */
86 static int aducm360_build_sector_list(struct flash_bank *bank)
90 /* sector size is 512 */
91 bank->num_sectors = bank->size / FLASH_SECTOR_SIZE;
92 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
93 for (unsigned i = 0; i < bank->num_sectors; ++i) {
94 bank->sectors[i].offset = offset;
95 bank->sectors[i].size = FLASH_SECTOR_SIZE;
96 offset += bank->sectors[i].size;
97 bank->sectors[i].is_erased = -1;
98 bank->sectors[i].is_protected = 0;
104 /* ----------------------------------------------------------------------- */
105 static int aducm360_mass_erase(struct target *target)
110 /* Clear any old status */
111 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
113 /* Enable the writing to the flash*/
114 aducm360_set_write_enable(target, 1);
116 /* Unlock for writing */
117 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
118 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
119 /* Issue the 'MASSERASE' command */
120 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000003);
122 /* Check the result */
123 res = aducm360_check_flash_completion(target, 3500);
124 if (res != ERROR_OK) {
125 LOG_ERROR("mass erase failed.");
126 aducm360_set_write_enable(target, 0);
127 res = ERROR_FLASH_OPERATION_FAILED;
133 /* ----------------------------------------------------------------------- */
134 static int aducm360_page_erase(struct target *target, uint32_t padd)
139 /* Clear any old status */
140 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
142 /* Enable the writing to the flash*/
143 aducm360_set_write_enable(target, 1);
145 /* Unlock for writing */
146 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
147 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
148 /* Write the sector address */
149 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0L, padd & 0xFFFF);
150 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0H, (padd>>16) & 0xFFFF);
151 /* Issue the 'ERASEPAGE' command */
152 target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000001);
154 /* Check the result */
155 res = aducm360_check_flash_completion(target, 50);
156 if (res != ERROR_OK) {
157 LOG_ERROR("page erase failed at 0x%08" PRIx32, padd);
158 aducm360_set_write_enable(target, 0);
159 res = ERROR_FLASH_OPERATION_FAILED;
165 /* ----------------------------------------------------------------------- */
166 static int aducm360_erase(struct flash_bank *bank, unsigned int first,
172 struct target *target = bank->target;
175 if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
176 res = aducm360_mass_erase(target);
178 count = last - first + 1;
179 for (i = 0; i < count; ++i) {
180 padd = bank->base + ((first+i)*FLASH_SECTOR_SIZE);
181 res = aducm360_page_erase(target, padd);
190 /* ----------------------------------------------------------------------- */
191 static int aducm360_write_block_sync(
192 struct flash_bank *bank,
193 const uint8_t *buffer,
197 struct target *target = bank->target;
198 uint32_t target_buffer_size = 8192;
199 struct working_area *helper;
200 struct working_area *target_buffer;
201 uint32_t address = bank->base + offset;
202 struct reg_param reg_params[8];
203 int retval = ERROR_OK;
204 uint32_t entry_point = 0, exit_point = 0;
206 struct armv7m_algorithm armv7m_algo;
208 static const uint32_t aducm360_flash_write_code[] = {
210 0x88AF4D10, 0x0704F047, 0x682F80AF, 0x600E6806,
211 0xF017882F, 0xF43F0F08, 0xF851AFFB, 0x42B77B04,
212 0x800DF040, 0x0004F100, 0xF47F3A04, 0x686FAFEF,
213 0x0704F027, 0xF04F80AF, 0xF0000400, 0xF04FB802,
214 0xBE000480, 0x40002800, 0x00015000, 0x20000000,
218 LOG_DEBUG("'aducm360_write_block_sync' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
221 /* ----- Check the destination area for a Long Word alignment ----- */
222 if (((count%4) != 0) || ((offset%4) != 0)) {
223 LOG_ERROR("write block must be multiple of four bytes in offset & length");
227 /* ----- Allocate space in the target's RAM for the helper code ----- */
228 if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
229 &helper) != ERROR_OK) {
230 LOG_WARNING("no working area available, can't do block memory writes");
231 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
234 /* ----- Upload the helper code to the space in the target's RAM ----- */
235 uint8_t code[sizeof(aducm360_flash_write_code)];
236 target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
237 aducm360_flash_write_code);
238 retval = target_write_buffer(target, helper->address, sizeof(code), code);
239 if (retval != ERROR_OK)
241 entry_point = helper->address;
243 /* ----- Allocate space in the target's RAM for the user application's object code ----- */
244 while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
245 LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
247 target_buffer_size /= 2;
248 if (target_buffer_size <= 256) { /* No room available */
249 LOG_WARNING("no large enough working area available, can't do block memory writes");
250 target_free_working_area(target, helper);
251 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
255 /* ----- Prepare the target for the helper ----- */
256 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
257 armv7m_algo.core_mode = ARM_MODE_THREAD;
259 init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /*SRC */
260 init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /*DST */
261 init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /*COUNT */
262 init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /*not used */
263 init_reg_param(®_params[4], "r4", 32, PARAM_IN); /*RESULT */
265 /* ===== Execute the Main Programming Loop! ===== */
267 uint32_t thisrun_count = (count > target_buffer_size) ? target_buffer_size : count;
269 /* ----- Upload the chunk ----- */
270 retval = target_write_buffer(target, target_buffer->address, thisrun_count, buffer);
271 if (retval != ERROR_OK)
273 /* Set the arguments for the helper */
274 buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address); /*SRC */
275 buf_set_u32(reg_params[1].value, 0, 32, address); /*DST */
276 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); /*COUNT */
277 buf_set_u32(reg_params[3].value, 0, 32, 0); /*NOT USED*/
279 retval = target_run_algorithm(target, 0, NULL, 5,
280 reg_params, entry_point, exit_point, 10000, &armv7m_algo);
281 if (retval != ERROR_OK) {
282 LOG_ERROR("error executing aducm360 flash write algorithm");
286 res = buf_get_u32(reg_params[4].value, 0, 32);
288 LOG_ERROR("aducm360 fast sync algorithm reports an error (%02" PRIX32 ")", res);
293 buffer += thisrun_count;
294 address += thisrun_count;
295 count -= thisrun_count;
298 target_free_working_area(target, target_buffer);
299 target_free_working_area(target, helper);
301 destroy_reg_param(®_params[0]);
302 destroy_reg_param(®_params[1]);
303 destroy_reg_param(®_params[2]);
304 destroy_reg_param(®_params[3]);
305 destroy_reg_param(®_params[4]);
310 /* ----------------------------------------------------------------------- */
311 static int aducm360_write_block_async(
312 struct flash_bank *bank,
313 const uint8_t *buffer,
317 struct target *target = bank->target;
318 uint32_t target_buffer_size = 1024;
319 struct working_area *helper;
320 struct working_area *target_buffer;
321 uint32_t address = bank->base + offset;
322 struct reg_param reg_params[9];
323 int retval = ERROR_OK;
324 uint32_t entry_point = 0, exit_point = 0;
327 struct armv7m_algorithm armv7m_algo;
329 static const uint32_t aducm360_flash_write_code[] = {
331 0x4050F8DF, 0xF04588A5, 0x80A50504, 0x8000F8D0,
332 0x0F00F1B8, 0x8016F000, 0x45476847, 0xAFF6F43F,
333 0x6B04F857, 0x6B04F842, 0xF0158825, 0xF43F0F08,
334 0x428FAFFB, 0xF100BF28, 0x60470708, 0xB10B3B01,
335 0xBFE4F7FF, 0xF02588A5, 0x80A50504, 0x0900F04F,
336 0xBE00BF00, 0x40002800, 0x20000000, 0x20000100,
340 LOG_DEBUG("'aducm360_write_block_async' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
343 /* ----- Check the destination area for a Long Word alignment ----- */
344 if (((count%4) != 0) || ((offset%4) != 0)) {
345 LOG_ERROR("write block must be multiple of four bytes in offset & length");
350 /* ----- Allocate space in the target's RAM for the helper code ----- */
351 if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
352 &helper) != ERROR_OK) {
353 LOG_WARNING("no working area available, can't do block memory writes");
354 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
357 /* ----- Upload the helper code to the space in the target's RAM ----- */
358 uint8_t code[sizeof(aducm360_flash_write_code)];
359 target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
360 aducm360_flash_write_code);
361 retval = target_write_buffer(target, helper->address, sizeof(code), code);
362 if (retval != ERROR_OK)
364 entry_point = helper->address;
366 /* ----- Allocate space in the target's RAM for the user application's object code ----- */
367 while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
368 LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
370 target_buffer_size /= 2;
371 if (target_buffer_size <= 256) { /* No room available */
372 LOG_WARNING("no large enough working area available, can't do block memory writes");
373 target_free_working_area(target, helper);
374 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
378 /* ----- Prepare the target for the helper ----- */
379 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
380 armv7m_algo.core_mode = ARM_MODE_THREAD;
382 init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /*SRCBEG */
383 init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /*SRCEND */
384 init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /*DST */
385 init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /*COUNT (LWs)*/
386 init_reg_param(®_params[4], "r9", 32, PARAM_IN); /*RESULT */
388 buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address);
389 buf_set_u32(reg_params[1].value, 0, 32, target_buffer->address + target_buffer->size);
390 buf_set_u32(reg_params[2].value, 0, 32, address);
391 buf_set_u32(reg_params[3].value, 0, 32, wcount);
393 retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
396 target_buffer->address, target_buffer->size,
397 entry_point, exit_point,
399 if (retval != ERROR_OK) {
400 LOG_ERROR("error executing aducm360 flash write algorithm");
402 res = buf_get_u32(reg_params[4].value, 0, 32); /*RESULT*/
404 LOG_ERROR("aducm360 fast async algorithm reports an error (%02" PRIX32 ")", res);
409 target_free_working_area(target, target_buffer);
410 target_free_working_area(target, helper);
412 destroy_reg_param(®_params[0]);
413 destroy_reg_param(®_params[1]);
414 destroy_reg_param(®_params[2]);
415 destroy_reg_param(®_params[3]);
416 destroy_reg_param(®_params[4]);
421 /* ----------------------------------------------------------------------- */
422 /* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
423 * back to another mechanism that does not require onboard RAM
425 * Caller should not check for other return values specifically
427 static int aducm360_write_block(struct flash_bank *bank,
428 const uint8_t *buffer,
436 return aducm360_write_block_sync(bank, buffer, offset, count);
438 return aducm360_write_block_async(bank, buffer, offset, count);
440 LOG_ERROR("aducm360_write_block was cancelled (no writing method was chosen)!");
441 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
445 /* ----------------------------------------------------------------------- */
446 #define FEESTA_WRDONE 0x00000008
448 static int aducm360_write_modified(struct flash_bank *bank,
449 const uint8_t *buffer,
456 struct target *target = bank->target;
458 LOG_DEBUG("performing slow write (offset=0x%08" PRIx32 ", count=0x%08" PRIx32 ")...",
461 /* Enable the writing to the flash */
462 aducm360_set_write_enable(target, 1);
464 /* Clear any old status */
465 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
467 for (i = 0; i < count; i += 4) {
469 for (j = 0; i < 4; i += 1)
470 *((uint8_t *)(&d) + j) = buffer[i+j];
471 target_write_u32(target, a, d);
473 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
474 } while (!(value & FEESTA_WRDONE));
476 aducm360_set_write_enable(target, 0);
481 /* ----------------------------------------------------------------------- */
482 static int aducm360_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
486 /* try using a block write */
487 retval = aducm360_write_block(bank, buffer, offset, count);
488 if (retval != ERROR_OK) {
489 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
490 /* if block write failed (no sufficient working area),
491 * use normal (slow) JTAG method */
492 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
494 retval = aducm360_write_modified(bank, buffer, offset, count);
495 if (retval != ERROR_OK) {
496 LOG_ERROR("slow write failed");
497 return ERROR_FLASH_OPERATION_FAILED;
504 /* ----------------------------------------------------------------------- */
505 static int aducm360_probe(struct flash_bank *bank)
510 /* ----------------------------------------------------------------------- */
511 /* sets FEECON0 bit 2
512 * enable = 1 enables writes & erases, 0 disables them */
513 static int aducm360_set_write_enable(struct target *target, int enable)
515 /* don't bother to preserve int enable bit here */
518 target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, &value);
522 value &= ~0x00000004;
523 target_write_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, value);
528 /* ----------------------------------------------------------------------- */
529 /* wait up to timeout_ms for controller to not be busy,
530 * then check whether the command passed or failed.
532 * this function sleeps 1ms between checks (after the first one),
533 * so in some cases may slow things down without a usleep after the first read */
534 static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms)
538 int64_t endtime = timeval_ms() + timeout_ms;
540 target_read_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEESTA, &v);
541 if ((v & 0x00000001) == 0)
544 if (timeval_ms() >= endtime)
548 if (!(v & 0x00000004)) /* b2 */
554 /* ----------------------------------------------------------------------- */
555 const struct flash_driver aducm360_flash = {
557 .flash_bank_command = aducm360_flash_bank_command,
558 .erase = aducm360_erase,
559 .write = aducm360_write,
560 .read = default_flash_read,
561 .probe = aducm360_probe,
562 .auto_probe = aducm360_probe,
563 .erase_check = default_flash_blank_check,