4 * Copyright (c) 2016 Andreas Färber
14 #include <helper/binarybuffer.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
18 #define FLASH_BASE 0x10000000
19 #define PAU_BASE 0x40000000
20 #define SCU_BASE 0x40010000
21 #define NVM_BASE 0x40050000
23 #define FLASH_CS0 (FLASH_BASE + 0xf00)
25 #define PAU_FLSIZE (PAU_BASE + 0x404)
27 #define SCU_IDCHIP (SCU_BASE + 0x004)
29 #define NVMSTATUS (NVM_BASE + 0x00)
30 #define NVMPROG (NVM_BASE + 0x04)
31 #define NVMCONF (NVM_BASE + 0x08)
33 #define NVMSTATUS_BUSY (1 << 0)
34 #define NVMSTATUS_VERR_MASK (0x3 << 2)
36 #define NVMPROG_ACTION_OPTYPE_IDLE_VERIFY (0 << 0)
37 #define NVMPROG_ACTION_OPTYPE_WRITE (1 << 0)
38 #define NVMPROG_ACTION_OPTYPE_PAGE_ERASE (2 << 0)
40 #define NVMPROG_ACTION_ONE_SHOT_ONCE (1 << 4)
41 #define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS (2 << 4)
43 #define NVMPROG_ACTION_VERIFY_EACH (1 << 6)
44 #define NVMPROG_ACTION_VERIFY_NO (2 << 6)
45 #define NVMPROG_ACTION_VERIFY_ARRAY (3 << 6)
47 #define NVMPROG_ACTION_IDLE 0x00
48 #define NVMPROG_ACTION_MASK 0xff
50 #define NVM_WORD_SIZE 4
51 #define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
52 #define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
54 struct xmc1xxx_flash_bank
{
58 static int xmc1xxx_nvm_set_idle(struct target
*target
)
60 return target_write_u16(target
, NVMPROG
, NVMPROG_ACTION_IDLE
);
63 static int xmc1xxx_nvm_check_idle(struct target
*target
)
68 retval
= target_read_u16(target
, NVMPROG
, &val
);
69 if (retval
!= ERROR_OK
)
71 if ((val
& NVMPROG_ACTION_MASK
) != NVMPROG_ACTION_IDLE
) {
72 LOG_WARNING("NVMPROG.ACTION");
73 retval
= xmc1xxx_nvm_set_idle(target
);
79 static int xmc1xxx_erase(struct flash_bank
*bank
, int first
, int last
)
81 struct target
*target
= bank
->target
;
82 struct working_area
*workarea
;
83 struct reg_param reg_params
[3];
84 struct armv7m_algorithm armv7m_algo
;
87 const uint8_t erase_code
[] = {
88 #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
91 LOG_DEBUG("Infineon XMC1000 erase sectors %d to %d", first
, last
);
93 if (bank
->target
->state
!= TARGET_HALTED
) {
94 LOG_WARNING("Cannot communicate... target not halted.");
95 return ERROR_TARGET_NOT_HALTED
;
98 retval
= xmc1xxx_nvm_check_idle(target
);
99 if (retval
!= ERROR_OK
)
102 retval
= target_alloc_working_area(target
, sizeof(erase_code
),
104 if (retval
!= ERROR_OK
) {
105 LOG_ERROR("No working area available.");
106 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
109 retval
= target_write_buffer(target
, workarea
->address
,
110 sizeof(erase_code
), erase_code
);
111 if (retval
!= ERROR_OK
)
114 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
115 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
117 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
118 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
119 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
121 buf_set_u32(reg_params
[0].value
, 0, 32, NVM_BASE
);
122 buf_set_u32(reg_params
[1].value
, 0, 32, bank
->base
+
123 bank
->sectors
[first
].offset
);
124 buf_set_u32(reg_params
[2].value
, 0, 32, bank
->base
+
125 bank
->sectors
[last
].offset
+ bank
->sectors
[last
].size
);
127 retval
= target_run_algorithm(target
,
129 ARRAY_SIZE(reg_params
), reg_params
,
130 workarea
->address
, 0,
132 if (retval
!= ERROR_OK
) {
133 LOG_ERROR("Error executing flash sector erase "
134 "programming algorithm");
135 retval
= xmc1xxx_nvm_set_idle(target
);
136 if (retval
!= ERROR_OK
)
137 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
138 retval
= ERROR_FLASH_OPERATION_FAILED
;
142 for (sector
= first
; sector
<= last
; sector
++)
143 bank
->sectors
[sector
].is_erased
= 1;
146 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
147 destroy_reg_param(®_params
[i
]);
150 target_free_working_area(target
, workarea
);
156 static int xmc1xxx_erase_check(struct flash_bank
*bank
)
158 struct target
*target
= bank
->target
;
159 struct working_area
*workarea
;
160 struct reg_param reg_params
[3];
161 struct armv7m_algorithm armv7m_algo
;
165 const uint8_t erase_check_code
[] = {
166 #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
169 if (bank
->target
->state
!= TARGET_HALTED
) {
170 LOG_WARNING("Cannot communicate... target not halted.");
171 return ERROR_TARGET_NOT_HALTED
;
174 retval
= target_alloc_working_area(target
, sizeof(erase_check_code
),
176 if (retval
!= ERROR_OK
) {
177 LOG_ERROR("No working area available.");
178 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
181 retval
= target_write_buffer(target
, workarea
->address
,
182 sizeof(erase_check_code
), erase_check_code
);
183 if (retval
!= ERROR_OK
)
186 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
187 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
189 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
190 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
191 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
193 buf_set_u32(reg_params
[0].value
, 0, 32, NVM_BASE
);
195 for (sector
= 0; sector
< bank
->num_sectors
; sector
++) {
196 uint32_t start
= bank
->base
+ bank
->sectors
[sector
].offset
;
197 buf_set_u32(reg_params
[1].value
, 0, 32, start
);
198 buf_set_u32(reg_params
[2].value
, 0, 32, start
+ bank
->sectors
[sector
].size
);
200 retval
= xmc1xxx_nvm_check_idle(target
);
201 if (retval
!= ERROR_OK
)
204 LOG_DEBUG("Erase-checking 0x%08" PRIx32
, start
);
205 retval
= target_run_algorithm(target
,
207 ARRAY_SIZE(reg_params
), reg_params
,
208 workarea
->address
, 0,
210 if (retval
!= ERROR_OK
) {
211 LOG_ERROR("Error executing flash sector erase check "
212 "programming algorithm");
213 retval
= xmc1xxx_nvm_set_idle(target
);
214 if (retval
!= ERROR_OK
)
215 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
216 retval
= ERROR_FLASH_OPERATION_FAILED
;
220 retval
= target_read_u16(target
, NVMSTATUS
, &val
);
221 if (retval
!= ERROR_OK
) {
222 LOG_ERROR("Couldn't read NVMSTATUS");
225 bank
->sectors
[sector
].is_erased
= (val
& NVMSTATUS_VERR_MASK
) ? 0 : 1;
231 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
232 destroy_reg_param(®_params
[i
]);
235 target_free_working_area(target
, workarea
);
241 static int xmc1xxx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
242 uint32_t offset
, uint32_t byte_count
)
244 struct target
*target
= bank
->target
;
245 struct working_area
*code_workarea
, *data_workarea
;
246 struct reg_param reg_params
[4];
247 struct armv7m_algorithm armv7m_algo
;
248 uint32_t block_count
= DIV_ROUND_UP(byte_count
, NVM_BLOCK_SIZE
);
251 const uint8_t write_code
[] = {
252 #include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
255 LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32
" (%" PRId32
" bytes)",
258 if (offset
& (NVM_BLOCK_SIZE
- 1)) {
259 LOG_ERROR("offset 0x%" PRIx32
" breaks required block alignment",
261 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
263 if (byte_count
& (NVM_BLOCK_SIZE
- 1)) {
264 LOG_WARNING("length %" PRId32
" is not block aligned, rounding up",
268 if (target
->state
!= TARGET_HALTED
) {
269 LOG_WARNING("Cannot communicate... target not halted.");
270 return ERROR_TARGET_NOT_HALTED
;
273 retval
= target_alloc_working_area(target
, sizeof(write_code
),
275 if (retval
!= ERROR_OK
) {
276 LOG_ERROR("No working area available for write code.");
277 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
280 retval
= target_write_buffer(target
, code_workarea
->address
,
281 sizeof(write_code
), write_code
);
282 if (retval
!= ERROR_OK
)
285 retval
= target_alloc_working_area(target
, MAX(NVM_BLOCK_SIZE
,
286 MIN(block_count
* NVM_BLOCK_SIZE
, target_get_working_area_avail(target
))),
288 if (retval
!= ERROR_OK
) {
289 LOG_ERROR("No working area available for write data.");
290 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
294 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
295 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
297 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
298 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
299 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
300 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
302 buf_set_u32(reg_params
[0].value
, 0, 32, NVM_BASE
);
304 while (byte_count
> 0) {
305 uint32_t blocks
= MIN(block_count
, data_workarea
->size
/ NVM_BLOCK_SIZE
);
306 uint32_t addr
= bank
->base
+ offset
;
308 LOG_DEBUG("copying %" PRId32
" bytes to SRAM " TARGET_ADDR_FMT
,
309 MIN(blocks
* NVM_BLOCK_SIZE
, byte_count
),
310 data_workarea
->address
);
312 retval
= target_write_buffer(target
, data_workarea
->address
,
313 MIN(blocks
* NVM_BLOCK_SIZE
, byte_count
), buffer
);
314 if (retval
!= ERROR_OK
) {
315 LOG_ERROR("Error writing data buffer");
316 retval
= ERROR_FLASH_OPERATION_FAILED
;
319 if (byte_count
< blocks
* NVM_BLOCK_SIZE
) {
320 retval
= target_write_memory(target
,
321 data_workarea
->address
+ byte_count
, 1,
322 blocks
* NVM_BLOCK_SIZE
- byte_count
,
323 &bank
->default_padded_value
);
324 if (retval
!= ERROR_OK
) {
325 LOG_ERROR("Error writing data padding");
326 retval
= ERROR_FLASH_OPERATION_FAILED
;
331 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRId32
"x)",
332 addr
, addr
+ blocks
* NVM_BLOCK_SIZE
- 1, blocks
);
334 retval
= xmc1xxx_nvm_check_idle(target
);
335 if (retval
!= ERROR_OK
)
338 buf_set_u32(reg_params
[1].value
, 0, 32, addr
);
339 buf_set_u32(reg_params
[2].value
, 0, 32, data_workarea
->address
);
340 buf_set_u32(reg_params
[3].value
, 0, 32, blocks
);
342 retval
= target_run_algorithm(target
,
344 ARRAY_SIZE(reg_params
), reg_params
,
345 code_workarea
->address
, 0,
346 5 * 60 * 1000, &armv7m_algo
);
347 if (retval
!= ERROR_OK
) {
348 LOG_ERROR("Error executing flash write "
349 "programming algorithm");
350 retval
= xmc1xxx_nvm_set_idle(target
);
351 if (retval
!= ERROR_OK
)
352 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
353 retval
= ERROR_FLASH_OPERATION_FAILED
;
357 block_count
-= blocks
;
358 offset
+= blocks
* NVM_BLOCK_SIZE
;
359 buffer
+= blocks
* NVM_BLOCK_SIZE
;
360 byte_count
-= MIN(blocks
* NVM_BLOCK_SIZE
, byte_count
);
367 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
368 destroy_reg_param(®_params
[i
]);
370 target_free_working_area(target
, data_workarea
);
373 target_free_working_area(target
, code_workarea
);
379 static int xmc1xxx_protect_check(struct flash_bank
*bank
)
382 int i
, num_protected
, retval
;
384 if (bank
->target
->state
!= TARGET_HALTED
) {
385 LOG_WARNING("Cannot communicate... target not halted.");
386 return ERROR_TARGET_NOT_HALTED
;
389 retval
= target_read_u32(bank
->target
, NVMCONF
, &nvmconf
);
390 if (retval
!= ERROR_OK
) {
391 LOG_ERROR("Cannot read NVMCONF register.");
394 LOG_DEBUG("NVMCONF = %08" PRIx32
, nvmconf
);
396 num_protected
= (nvmconf
>> 4) & 0xff;
398 for (i
= 0; i
< bank
->num_sectors
; i
++)
399 bank
->sectors
[i
].is_protected
= (i
< num_protected
) ? 1 : 0;
404 static int xmc1xxx_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
409 if (bank
->target
->state
!= TARGET_HALTED
) {
410 LOG_WARNING("Cannot communicate... target not halted.");
411 return ERROR_TARGET_NOT_HALTED
;
414 /* Obtain the 8-word Chip Identification Number */
415 for (i
= 0; i
< 7; i
++) {
416 retval
= target_read_u32(bank
->target
, FLASH_CS0
+ i
* 4, &chipid
[i
]);
417 if (retval
!= ERROR_OK
) {
418 LOG_ERROR("Cannot read CS0 register %i.", i
);
421 LOG_DEBUG("ID[%d] = %08" PRIX32
, i
, chipid
[i
]);
423 retval
= target_read_u32(bank
->target
, SCU_BASE
+ 0x000, &chipid
[7]);
424 if (retval
!= ERROR_OK
) {
425 LOG_ERROR("Cannot read DBGROMID register.");
428 LOG_DEBUG("ID[7] = %08" PRIX32
, chipid
[7]);
430 snprintf(buf
, buf_size
, "XMC%" PRIx32
"00 %X flash %uKB ROM %uKB SRAM %uKB",
431 (chipid
[0] >> 12) & 0xff,
432 0xAA + (chipid
[7] >> 28) - 1,
433 (((chipid
[6] >> 12) & 0x3f) - 1) * 4,
434 (((chipid
[4] >> 8) & 0x3f) * 256) / 1024,
435 (((chipid
[5] >> 8) & 0x1f) * 256 * 4) / 1024);
440 static int xmc1xxx_probe(struct flash_bank
*bank
)
442 struct xmc1xxx_flash_bank
*xmc_bank
= bank
->driver_priv
;
443 uint32_t flash_addr
= bank
->base
;
444 uint32_t idchip
, flsize
;
447 if (xmc_bank
->probed
)
450 if (bank
->target
->state
!= TARGET_HALTED
) {
451 LOG_WARNING("Cannot communicate... target not halted.");
452 return ERROR_TARGET_NOT_HALTED
;
455 retval
= target_read_u32(bank
->target
, SCU_IDCHIP
, &idchip
);
456 if (retval
!= ERROR_OK
) {
457 LOG_ERROR("Cannot read IDCHIP register.");
461 if ((idchip
& 0xffff0000) != 0x10000) {
462 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
466 LOG_DEBUG("IDCHIP = %08" PRIx32
, idchip
);
468 retval
= target_read_u32(bank
->target
, PAU_FLSIZE
, &flsize
);
469 if (retval
!= ERROR_OK
) {
470 LOG_ERROR("Cannot read FLSIZE register.");
474 bank
->num_sectors
= 1 + ((flsize
>> 12) & 0x3f) - 1;
475 bank
->size
= bank
->num_sectors
* 4 * 1024;
476 bank
->sectors
= calloc(bank
->num_sectors
,
477 sizeof(struct flash_sector
));
478 for (i
= 0; i
< bank
->num_sectors
; i
++) {
480 bank
->sectors
[i
].size
= 0x200;
481 bank
->sectors
[i
].offset
= 0xE00;
482 flash_addr
+= 0x1000;
484 bank
->sectors
[i
].size
= 4 * 1024;
485 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
486 flash_addr
+= bank
->sectors
[i
].size
;
488 bank
->sectors
[i
].is_erased
= -1;
489 bank
->sectors
[i
].is_protected
= -1;
492 xmc_bank
->probed
= true;
497 static int xmc1xxx_auto_probe(struct flash_bank
*bank
)
499 struct xmc1xxx_flash_bank
*xmc_bank
= bank
->driver_priv
;
501 if (xmc_bank
->probed
)
504 return xmc1xxx_probe(bank
);
507 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command
)
509 struct xmc1xxx_flash_bank
*xmc_bank
;
511 xmc_bank
= malloc(sizeof(struct xmc1xxx_flash_bank
));
513 return ERROR_FLASH_OPERATION_FAILED
;
515 xmc_bank
->probed
= false;
517 bank
->driver_priv
= xmc_bank
;
522 static const struct command_registration xmc1xxx_exec_command_handlers
[] = {
523 COMMAND_REGISTRATION_DONE
526 static const struct command_registration xmc1xxx_command_handlers
[] = {
530 .help
= "xmc1xxx flash command group",
532 .chain
= xmc1xxx_exec_command_handlers
,
534 COMMAND_REGISTRATION_DONE
537 struct flash_driver xmc1xxx_flash
= {
539 .commands
= xmc1xxx_command_handlers
,
540 .flash_bank_command
= xmc1xxx_flash_bank_command
,
541 .info
= xmc1xxx_get_info_command
,
542 .probe
= xmc1xxx_probe
,
543 .auto_probe
= xmc1xxx_auto_probe
,
544 .protect_check
= xmc1xxx_protect_check
,
545 .read
= default_flash_read
,
546 .erase
= xmc1xxx_erase
,
547 .erase_check
= xmc1xxx_erase_check
,
548 .write
= xmc1xxx_write
,
549 .free_driver_priv
= default_flash_free_driver_priv
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)