1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
13 #include <helper/binarybuffer.h>
14 #include <helper/time_support.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
17 #include <target/image.h>
19 #define FLASH_TIMEOUT 8000
22 const char *family_name
;
26 uint32_t sector_length
;
28 struct working_area
*working_area
;
29 struct armv7m_algorithm armv7m_info
;
30 const uint8_t *algo_code
;
32 uint32_t algo_working_size
;
33 uint32_t buffer_addr
[2];
34 uint32_t params_addr
[2];
37 /* Flash helper algorithm for CC26x0 Chameleon targets */
38 static const uint8_t cc26x0_algo
[] = {
39 #include "../../../contrib/loaders/flash/cc26xx/cc26x0_algo.inc"
42 /* Flash helper algorithm for CC26x2 Agama targets */
43 static const uint8_t cc26x2_algo
[] = {
44 #include "../../../contrib/loaders/flash/cc26xx/cc26x2_algo.inc"
47 static int cc26xx_auto_probe(struct flash_bank
*bank
);
49 static uint32_t cc26xx_device_type(uint32_t icepick_id
, uint32_t user_id
)
51 uint32_t device_type
= 0;
53 switch (icepick_id
& ICEPICK_ID_MASK
) {
54 case CC26X0_ICEPICK_ID
:
55 device_type
= CC26X0_TYPE
;
57 case CC26X1_ICEPICK_ID
:
58 device_type
= CC26X1_TYPE
;
60 case CC13X0_ICEPICK_ID
:
61 device_type
= CC13X0_TYPE
;
63 case CC13X2_CC26X2_ICEPICK_ID
:
65 if ((user_id
& USER_ID_CC13_MASK
) != 0)
66 device_type
= CC13X2_TYPE
;
68 device_type
= CC26X2_TYPE
;
75 static uint32_t cc26xx_sector_length(uint32_t icepick_id
)
77 uint32_t sector_length
;
79 switch (icepick_id
& ICEPICK_ID_MASK
) {
80 case CC26X0_ICEPICK_ID
:
81 case CC26X1_ICEPICK_ID
:
82 case CC13X0_ICEPICK_ID
:
83 /* Chameleon family device */
84 sector_length
= CC26X0_SECTOR_LENGTH
;
86 case CC13X2_CC26X2_ICEPICK_ID
:
88 /* Agama family device */
89 sector_length
= CC26X2_SECTOR_LENGTH
;
96 static int cc26xx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
98 struct target
*target
= bank
->target
;
99 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
101 uint32_t status_addr
= params_addr
+ CC26XX_STATUS_OFFSET
;
102 uint32_t status
= CC26XX_BUFFER_FULL
;
104 long long elapsed_ms
;
106 int retval
= ERROR_OK
;
108 start_ms
= timeval_ms();
109 while (status
== CC26XX_BUFFER_FULL
) {
110 retval
= target_read_u32(target
, status_addr
, &status
);
111 if (retval
!= ERROR_OK
)
114 elapsed_ms
= timeval_ms() - start_ms
;
115 if (elapsed_ms
> 500)
117 if (elapsed_ms
> FLASH_TIMEOUT
)
121 if (status
!= CC26XX_BUFFER_EMPTY
) {
122 LOG_ERROR("%s: Flash operation failed", cc26xx_bank
->family_name
);
129 static int cc26xx_init(struct flash_bank
*bank
)
131 struct target
*target
= bank
->target
;
132 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
136 /* Make sure we've probed the flash to get the device and size */
137 retval
= cc26xx_auto_probe(bank
);
138 if (retval
!= ERROR_OK
)
141 /* Check for working area to use for flash helper algorithm */
142 target_free_working_area(target
, cc26xx_bank
->working_area
);
143 cc26xx_bank
->working_area
= NULL
;
145 retval
= target_alloc_working_area(target
, cc26xx_bank
->algo_working_size
,
146 &cc26xx_bank
->working_area
);
147 if (retval
!= ERROR_OK
)
150 /* Confirm the defined working address is the area we need to use */
151 if (cc26xx_bank
->working_area
->address
!= CC26XX_ALGO_BASE_ADDRESS
)
152 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
154 /* Write flash helper algorithm into target memory */
155 retval
= target_write_buffer(target
, CC26XX_ALGO_BASE_ADDRESS
,
156 cc26xx_bank
->algo_size
, cc26xx_bank
->algo_code
);
157 if (retval
!= ERROR_OK
) {
158 LOG_ERROR("%s: Failed to load flash helper algorithm",
159 cc26xx_bank
->family_name
);
160 target_free_working_area(target
, cc26xx_bank
->working_area
);
161 cc26xx_bank
->working_area
= NULL
;
165 /* Initialize the ARMv7 specific info to run the algorithm */
166 cc26xx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
167 cc26xx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
169 /* Begin executing the flash helper algorithm */
170 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
171 CC26XX_ALGO_BASE_ADDRESS
, 0, &cc26xx_bank
->armv7m_info
);
172 if (retval
!= ERROR_OK
) {
173 LOG_ERROR("%s: Failed to start flash helper algorithm",
174 cc26xx_bank
->family_name
);
175 target_free_working_area(target
, cc26xx_bank
->working_area
);
176 cc26xx_bank
->working_area
= NULL
;
181 * At this point, the algorithm is running on the target and
182 * ready to receive commands and data to flash the target
188 static int cc26xx_quit(struct flash_bank
*bank
)
190 struct target
*target
= bank
->target
;
191 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
195 /* Regardless of the algo's status, attempt to halt the target */
196 (void)target_halt(target
);
198 /* Now confirm target halted and clean up from flash helper algorithm */
199 retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0, FLASH_TIMEOUT
,
200 &cc26xx_bank
->armv7m_info
);
202 target_free_working_area(target
, cc26xx_bank
->working_area
);
203 cc26xx_bank
->working_area
= NULL
;
208 static int cc26xx_mass_erase(struct flash_bank
*bank
)
210 struct target
*target
= bank
->target
;
211 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
212 struct cc26xx_algo_params algo_params
;
216 if (target
->state
!= TARGET_HALTED
) {
217 LOG_ERROR("Target not halted");
218 return ERROR_TARGET_NOT_HALTED
;
221 retval
= cc26xx_init(bank
);
222 if (retval
!= ERROR_OK
)
225 /* Initialize algorithm parameters */
226 buf_set_u32(algo_params
.address
, 0, 32, 0);
227 buf_set_u32(algo_params
.length
, 0, 32, 4);
228 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_ALL
);
229 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
231 /* Issue flash helper algorithm parameters for mass erase */
232 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
233 sizeof(algo_params
), (uint8_t *)&algo_params
);
235 /* Wait for command to complete */
236 if (retval
== ERROR_OK
)
237 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
239 /* Regardless of errors, try to close down algo */
240 (void)cc26xx_quit(bank
);
245 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command
)
247 struct cc26xx_bank
*cc26xx_bank
;
250 return ERROR_COMMAND_SYNTAX_ERROR
;
252 cc26xx_bank
= malloc(sizeof(struct cc26xx_bank
));
256 /* Initialize private flash information */
257 memset((void *)cc26xx_bank
, 0x00, sizeof(struct cc26xx_bank
));
258 cc26xx_bank
->family_name
= "cc26xx";
259 cc26xx_bank
->device_type
= CC26XX_NO_TYPE
;
260 cc26xx_bank
->sector_length
= 0x1000;
262 /* Finish initialization of bank */
263 bank
->driver_priv
= cc26xx_bank
;
268 static int cc26xx_erase(struct flash_bank
*bank
, unsigned int first
,
271 struct target
*target
= bank
->target
;
272 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
273 struct cc26xx_algo_params algo_params
;
279 if (target
->state
!= TARGET_HALTED
) {
280 LOG_ERROR("Target not halted");
281 return ERROR_TARGET_NOT_HALTED
;
284 /* Do a mass erase if user requested all sectors of flash */
285 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
286 /* Request mass erase of flash */
287 return cc26xx_mass_erase(bank
);
290 address
= first
* cc26xx_bank
->sector_length
;
291 length
= (last
- first
+ 1) * cc26xx_bank
->sector_length
;
293 retval
= cc26xx_init(bank
);
294 if (retval
!= ERROR_OK
)
297 /* Set up algorithm parameters for erase command */
298 buf_set_u32(algo_params
.address
, 0, 32, address
);
299 buf_set_u32(algo_params
.length
, 0, 32, length
);
300 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_SECTORS
);
301 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
303 /* Issue flash helper algorithm parameters for erase */
304 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
305 sizeof(algo_params
), (uint8_t *)&algo_params
);
307 /* If no error, wait for erase to finish */
308 if (retval
== ERROR_OK
)
309 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
311 /* Regardless of errors, try to close down algo */
312 (void)cc26xx_quit(bank
);
317 static int cc26xx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
318 uint32_t offset
, uint32_t count
)
320 struct target
*target
= bank
->target
;
321 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
322 struct cc26xx_algo_params algo_params
[2];
325 long long elapsed_ms
;
331 if (target
->state
!= TARGET_HALTED
) {
332 LOG_ERROR("Target not halted");
333 return ERROR_TARGET_NOT_HALTED
;
336 retval
= cc26xx_init(bank
);
337 if (retval
!= ERROR_OK
)
340 /* Initialize algorithm parameters to default values */
341 buf_set_u32(algo_params
[0].command
, 0, 32, CC26XX_CMD_PROGRAM
);
342 buf_set_u32(algo_params
[1].command
, 0, 32, CC26XX_CMD_PROGRAM
);
344 /* Write requested data, ping-ponging between two buffers */
346 start_ms
= timeval_ms();
347 address
= bank
->base
+ offset
;
350 if (count
> cc26xx_bank
->sector_length
)
351 size
= cc26xx_bank
->sector_length
;
355 /* Put next block of data to flash into buffer */
356 retval
= target_write_buffer(target
, cc26xx_bank
->buffer_addr
[index
],
358 if (retval
!= ERROR_OK
) {
359 LOG_ERROR("Unable to write data to target memory");
363 /* Update algo parameters for next block */
364 buf_set_u32(algo_params
[index
].address
, 0, 32, address
);
365 buf_set_u32(algo_params
[index
].length
, 0, 32, size
);
366 buf_set_u32(algo_params
[index
].status
, 0, 32, CC26XX_BUFFER_FULL
);
368 /* Issue flash helper algorithm parameters for block write */
369 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[index
],
370 sizeof(algo_params
[index
]), (uint8_t *)&algo_params
[index
]);
371 if (retval
!= ERROR_OK
)
374 /* Wait for next ping pong buffer to be ready */
376 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
377 if (retval
!= ERROR_OK
)
384 elapsed_ms
= timeval_ms() - start_ms
;
385 if (elapsed_ms
> 500)
389 /* If no error yet, wait for last buffer to finish */
390 if (retval
== ERROR_OK
) {
392 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
395 /* Regardless of errors, try to close down algo */
396 (void)cc26xx_quit(bank
);
401 static int cc26xx_probe(struct flash_bank
*bank
)
403 struct target
*target
= bank
->target
;
404 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
406 uint32_t sector_length
;
413 retval
= target_read_u32(target
, FCFG1_ICEPICK_ID
, &value
);
414 if (retval
!= ERROR_OK
)
416 cc26xx_bank
->icepick_id
= value
;
418 retval
= target_read_u32(target
, FCFG1_USER_ID
, &value
);
419 if (retval
!= ERROR_OK
)
421 cc26xx_bank
->user_id
= value
;
423 cc26xx_bank
->device_type
= cc26xx_device_type(cc26xx_bank
->icepick_id
,
424 cc26xx_bank
->user_id
);
426 sector_length
= cc26xx_sector_length(cc26xx_bank
->icepick_id
);
428 /* Set up appropriate flash helper algorithm */
429 switch (cc26xx_bank
->icepick_id
& ICEPICK_ID_MASK
) {
430 case CC26X0_ICEPICK_ID
:
431 case CC26X1_ICEPICK_ID
:
432 case CC13X0_ICEPICK_ID
:
433 /* Chameleon family device */
434 cc26xx_bank
->algo_code
= cc26x0_algo
;
435 cc26xx_bank
->algo_size
= sizeof(cc26x0_algo
);
436 cc26xx_bank
->algo_working_size
= CC26X0_WORKING_SIZE
;
437 cc26xx_bank
->buffer_addr
[0] = CC26X0_ALGO_BUFFER_0
;
438 cc26xx_bank
->buffer_addr
[1] = CC26X0_ALGO_BUFFER_1
;
439 cc26xx_bank
->params_addr
[0] = CC26X0_ALGO_PARAMS_0
;
440 cc26xx_bank
->params_addr
[1] = CC26X0_ALGO_PARAMS_1
;
441 max_sectors
= CC26X0_MAX_SECTORS
;
443 case CC13X2_CC26X2_ICEPICK_ID
:
445 /* Agama family device */
446 cc26xx_bank
->algo_code
= cc26x2_algo
;
447 cc26xx_bank
->algo_size
= sizeof(cc26x2_algo
);
448 cc26xx_bank
->algo_working_size
= CC26X2_WORKING_SIZE
;
449 cc26xx_bank
->buffer_addr
[0] = CC26X2_ALGO_BUFFER_0
;
450 cc26xx_bank
->buffer_addr
[1] = CC26X2_ALGO_BUFFER_1
;
451 cc26xx_bank
->params_addr
[0] = CC26X2_ALGO_PARAMS_0
;
452 cc26xx_bank
->params_addr
[1] = CC26X2_ALGO_PARAMS_1
;
453 max_sectors
= CC26X2_MAX_SECTORS
;
457 retval
= target_read_u32(target
, CC26XX_FLASH_SIZE_INFO
, &value
);
458 if (retval
!= ERROR_OK
)
460 num_sectors
= value
& 0xff;
461 if (num_sectors
> max_sectors
)
462 num_sectors
= max_sectors
;
464 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
468 bank
->base
= CC26XX_FLASH_BASE_ADDR
;
469 bank
->num_sectors
= num_sectors
;
470 bank
->size
= num_sectors
* sector_length
;
471 bank
->write_start_alignment
= 0;
472 bank
->write_end_alignment
= 0;
473 cc26xx_bank
->sector_length
= sector_length
;
475 for (int i
= 0; i
< num_sectors
; i
++) {
476 bank
->sectors
[i
].offset
= i
* sector_length
;
477 bank
->sectors
[i
].size
= sector_length
;
478 bank
->sectors
[i
].is_erased
= -1;
479 bank
->sectors
[i
].is_protected
= 0;
482 /* We've successfully determined the stats on the flash bank */
483 cc26xx_bank
->probed
= true;
485 /* If we fall through to here, then all went well */
490 static int cc26xx_auto_probe(struct flash_bank
*bank
)
492 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
494 int retval
= ERROR_OK
;
496 if (!cc26xx_bank
->probed
)
497 retval
= cc26xx_probe(bank
);
502 static int cc26xx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
504 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
507 switch (cc26xx_bank
->device_type
) {
525 device
= "Unrecognized";
529 command_print_sameline(cmd
,
530 "%s device: ICEPick ID 0x%08" PRIx32
", USER ID 0x%08" PRIx32
"\n",
531 device
, cc26xx_bank
->icepick_id
, cc26xx_bank
->user_id
);
536 const struct flash_driver cc26xx_flash
= {
538 .flash_bank_command
= cc26xx_flash_bank_command
,
539 .erase
= cc26xx_erase
,
540 .write
= cc26xx_write
,
541 .read
= default_flash_read
,
542 .probe
= cc26xx_probe
,
543 .auto_probe
= cc26xx_auto_probe
,
544 .erase_check
= default_flash_blank_check
,
546 .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)