249
289
uint8_t jump_gate[8];
251
291
/* make sure we have a working area */
252
if (target_alloc_working_area(target, 172, &lpc2000_info->iap_working_area) != ERROR_OK)
292
if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK)
254
294
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
255
295
return ERROR_FLASH_OPERATION_FAILED;
258
298
/* write IAP code to working area */
259
target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
260
target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
299
switch(lpc2000_info->variant)
302
target_buffer_set_u32(target, jump_gate, ARMV7M_T_BX(12));
303
target_buffer_set_u32(target, jump_gate + 4, ARMV7M_T_B(0xfffffe));
307
target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
308
target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
311
LOG_ERROR("BUG: unknown bank->size encountered");
261
315
if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
317
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address);
267
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
268
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
269
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
322
switch(lpc2000_info->variant)
325
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
326
armv7m_info.core_mode = ARMV7M_MODE_ANY;
327
iap_entry_point = 0x1fff1ff1;
331
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
332
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
333
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
334
iap_entry_point = 0x7ffffff1;
337
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
271
341
/* command parameter table */
272
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 4 * 6, PARAM_OUT);
342
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT);
273
343
target_buffer_set_u32(target, mem_params[0].value, code);
274
target_buffer_set_u32(target, mem_params[0].value + 0x4, param_table[0]);
275
target_buffer_set_u32(target, mem_params[0].value + 0x8, param_table[1]);
276
target_buffer_set_u32(target, mem_params[0].value + 0xc, param_table[2]);
344
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
345
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
346
target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
277
347
target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
278
348
target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);
280
350
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
281
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x8);
351
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
283
353
/* command result table */
284
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 4 * 3, PARAM_IN);
354
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
286
356
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
287
357
buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
289
359
/* IAP entry point */
290
360
init_reg_param(®_params[2], "r12", 32, PARAM_OUT);
291
buf_set_u32(reg_params[2].value, 0, 32, 0x7ffffff1);
294
init_reg_param(®_params[3], "r13_svc", 32, PARAM_OUT);
295
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xac);
298
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
299
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x4);
301
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
303
status_code = buf_get_u32(mem_params[1].value, 0, 32);
304
result_table[0] = target_buffer_get_u32(target, mem_params[1].value);
305
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 4);
361
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
363
switch(lpc2000_info->variant)
367
init_reg_param(®_params[3], "sp", 32, PARAM_OUT);
368
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
371
init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
372
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
374
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv7m_info);
379
init_reg_param(®_params[3], "r13_svc", 32, PARAM_OUT);
380
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
383
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
384
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x04);
386
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
389
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
394
status_code = target_buffer_get_u32(target, mem_params[1].value);
395
result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
396
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
397
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
398
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
400
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32,
401
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
307
403
destroy_mem_param(&mem_params[0]);
308
404
destroy_mem_param(&mem_params[1]);
515
619
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
517
621
uint32_t checksum = 0;
519
623
for (i = 0; i < 8; i++)
521
LOG_DEBUG("0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
625
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
626
if (i != lpc2000_info->checksum_vector)
523
627
checksum += buf_get_u32(buffer + (i * 4), 0, 32);
525
629
checksum = 0 - checksum;
526
630
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
528
uint32_t original_value = buf_get_u32(buffer + (5 * 4), 0, 32);
632
uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
529
633
if (original_value != checksum)
531
LOG_WARNING("Verification will fail since checksum in image(0x%8.8" PRIx32 ") written to flash was different from calculated vector checksum(0x%8.8" PRIx32 ").",
635
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").",
532
636
original_value, checksum);
533
637
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
536
buf_set_u32(buffer + 0x14, 0, 32, checksum);
640
buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
539
643
/* allocate a working area */