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 static int cc26xx_auto_probe(struct flash_bank
*bank
);
39 static uint32_t cc26xx_device_type(uint32_t icepick_id
, uint32_t user_id
)
41 uint32_t device_type
= 0;
43 switch (icepick_id
& ICEPICK_ID_MASK
) {
44 case CC26X0_ICEPICK_ID
:
45 device_type
= CC26X0_TYPE
;
47 case CC26X1_ICEPICK_ID
:
48 device_type
= CC26X1_TYPE
;
50 case CC13X0_ICEPICK_ID
:
51 device_type
= CC13X0_TYPE
;
53 case CC13X2_CC26X2_ICEPICK_ID
:
55 if ((user_id
& USER_ID_CC13_MASK
) != 0)
56 device_type
= CC13X2_TYPE
;
58 device_type
= CC26X2_TYPE
;
65 static uint32_t cc26xx_sector_length(uint32_t icepick_id
)
67 uint32_t sector_length
;
69 switch (icepick_id
& ICEPICK_ID_MASK
) {
70 case CC26X0_ICEPICK_ID
:
71 case CC26X1_ICEPICK_ID
:
72 case CC13X0_ICEPICK_ID
:
73 /* Chameleon family device */
74 sector_length
= CC26X0_SECTOR_LENGTH
;
76 case CC13X2_CC26X2_ICEPICK_ID
:
78 /* Agama family device */
79 sector_length
= CC26X2_SECTOR_LENGTH
;
86 static int cc26xx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
88 struct target
*target
= bank
->target
;
89 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
91 uint32_t status_addr
= params_addr
+ CC26XX_STATUS_OFFSET
;
92 uint32_t status
= CC26XX_BUFFER_FULL
;
96 int retval
= ERROR_OK
;
98 start_ms
= timeval_ms();
99 while (status
== CC26XX_BUFFER_FULL
) {
100 retval
= target_read_u32(target
, status_addr
, &status
);
101 if (retval
!= ERROR_OK
)
104 elapsed_ms
= timeval_ms() - start_ms
;
105 if (elapsed_ms
> 500)
107 if (elapsed_ms
> FLASH_TIMEOUT
)
111 if (status
!= CC26XX_BUFFER_EMPTY
) {
112 LOG_ERROR("%s: Flash operation failed", cc26xx_bank
->family_name
);
119 static int cc26xx_init(struct flash_bank
*bank
)
121 struct target
*target
= bank
->target
;
122 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
126 /* Make sure we've probed the flash to get the device and size */
127 retval
= cc26xx_auto_probe(bank
);
128 if (retval
!= ERROR_OK
)
131 /* Check for working area to use for flash helper algorithm */
132 target_free_working_area(target
, cc26xx_bank
->working_area
);
133 cc26xx_bank
->working_area
= NULL
;
135 retval
= target_alloc_working_area(target
, cc26xx_bank
->algo_working_size
,
136 &cc26xx_bank
->working_area
);
137 if (retval
!= ERROR_OK
)
140 /* Confirm the defined working address is the area we need to use */
141 if (cc26xx_bank
->working_area
->address
!= CC26XX_ALGO_BASE_ADDRESS
)
142 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
144 /* Write flash helper algorithm into target memory */
145 retval
= target_write_buffer(target
, CC26XX_ALGO_BASE_ADDRESS
,
146 cc26xx_bank
->algo_size
, cc26xx_bank
->algo_code
);
147 if (retval
!= ERROR_OK
) {
148 LOG_ERROR("%s: Failed to load flash helper algorithm",
149 cc26xx_bank
->family_name
);
150 target_free_working_area(target
, cc26xx_bank
->working_area
);
151 cc26xx_bank
->working_area
= NULL
;
155 /* Initialize the ARMv7 specific info to run the algorithm */
156 cc26xx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
157 cc26xx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
159 /* Begin executing the flash helper algorithm */
160 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
161 CC26XX_ALGO_BASE_ADDRESS
, 0, &cc26xx_bank
->armv7m_info
);
162 if (retval
!= ERROR_OK
) {
163 LOG_ERROR("%s: Failed to start flash helper algorithm",
164 cc26xx_bank
->family_name
);
165 target_free_working_area(target
, cc26xx_bank
->working_area
);
166 cc26xx_bank
->working_area
= NULL
;
171 * At this point, the algorithm is running on the target and
172 * ready to receive commands and data to flash the target
178 static int cc26xx_quit(struct flash_bank
*bank
)
180 struct target
*target
= bank
->target
;
181 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
185 /* Regardless of the algo's status, attempt to halt the target */
186 (void)target_halt(target
);
188 /* Now confirm target halted and clean up from flash helper algorithm */
189 retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0, FLASH_TIMEOUT
,
190 &cc26xx_bank
->armv7m_info
);
192 target_free_working_area(target
, cc26xx_bank
->working_area
);
193 cc26xx_bank
->working_area
= NULL
;
198 static int cc26xx_mass_erase(struct flash_bank
*bank
)
200 struct target
*target
= bank
->target
;
201 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
202 struct cc26xx_algo_params algo_params
;
206 if (target
->state
!= TARGET_HALTED
) {
207 LOG_ERROR("Target not halted");
208 return ERROR_TARGET_NOT_HALTED
;
211 retval
= cc26xx_init(bank
);
212 if (retval
!= ERROR_OK
)
215 /* Initialize algorithm parameters */
216 buf_set_u32(algo_params
.address
, 0, 32, 0);
217 buf_set_u32(algo_params
.length
, 0, 32, 4);
218 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_ALL
);
219 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
221 /* Issue flash helper algorithm parameters for mass erase */
222 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
223 sizeof(algo_params
), (uint8_t *)&algo_params
);
225 /* Wait for command to complete */
226 if (retval
== ERROR_OK
)
227 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
229 /* Regardless of errors, try to close down algo */
230 (void)cc26xx_quit(bank
);
235 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command
)
237 struct cc26xx_bank
*cc26xx_bank
;
240 return ERROR_COMMAND_SYNTAX_ERROR
;
242 cc26xx_bank
= malloc(sizeof(struct cc26xx_bank
));
246 /* Initialize private flash information */
247 memset((void *)cc26xx_bank
, 0x00, sizeof(struct cc26xx_bank
));
248 cc26xx_bank
->family_name
= "cc26xx";
249 cc26xx_bank
->device_type
= CC26XX_NO_TYPE
;
250 cc26xx_bank
->sector_length
= 0x1000;
252 /* Finish initialization of bank */
253 bank
->driver_priv
= cc26xx_bank
;
259 static int cc26xx_erase(struct flash_bank
*bank
, unsigned int first
,
262 struct target
*target
= bank
->target
;
263 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
264 struct cc26xx_algo_params algo_params
;
270 if (target
->state
!= TARGET_HALTED
) {
271 LOG_ERROR("Target not halted");
272 return ERROR_TARGET_NOT_HALTED
;
275 /* Do a mass erase if user requested all sectors of flash */
276 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
277 /* Request mass erase of flash */
278 return cc26xx_mass_erase(bank
);
281 address
= first
* cc26xx_bank
->sector_length
;
282 length
= (last
- first
+ 1) * cc26xx_bank
->sector_length
;
284 retval
= cc26xx_init(bank
);
285 if (retval
!= ERROR_OK
)
288 /* Set up algorithm parameters for erase command */
289 buf_set_u32(algo_params
.address
, 0, 32, address
);
290 buf_set_u32(algo_params
.length
, 0, 32, length
);
291 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_SECTORS
);
292 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
294 /* Issue flash helper algorithm parameters for erase */
295 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
296 sizeof(algo_params
), (uint8_t *)&algo_params
);
298 /* If no error, wait for erase to finish */
299 if (retval
== ERROR_OK
)
300 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
302 /* Regardless of errors, try to close down algo */
303 (void)cc26xx_quit(bank
);
308 static int cc26xx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
309 uint32_t offset
, uint32_t count
)
311 struct target
*target
= bank
->target
;
312 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
313 struct cc26xx_algo_params algo_params
[2];
316 long long elapsed_ms
;
322 if (target
->state
!= TARGET_HALTED
) {
323 LOG_ERROR("Target not halted");
324 return ERROR_TARGET_NOT_HALTED
;
327 retval
= cc26xx_init(bank
);
328 if (retval
!= ERROR_OK
)
331 /* Initialize algorithm parameters to default values */
332 buf_set_u32(algo_params
[0].command
, 0, 32, CC26XX_CMD_PROGRAM
);
333 buf_set_u32(algo_params
[1].command
, 0, 32, CC26XX_CMD_PROGRAM
);
335 /* Write requested data, ping-ponging between two buffers */
337 start_ms
= timeval_ms();
338 address
= bank
->base
+ offset
;
341 if (count
> cc26xx_bank
->sector_length
)
342 size
= cc26xx_bank
->sector_length
;
346 /* Put next block of data to flash into buffer */
347 retval
= target_write_buffer(target
, cc26xx_bank
->buffer_addr
[index
],
349 if (retval
!= ERROR_OK
) {
350 LOG_ERROR("Unable to write data to target memory");
354 /* Update algo parameters for next block */
355 buf_set_u32(algo_params
[index
].address
, 0, 32, address
);
356 buf_set_u32(algo_params
[index
].length
, 0, 32, size
);
357 buf_set_u32(algo_params
[index
].status
, 0, 32, CC26XX_BUFFER_FULL
);
359 /* Issue flash helper algorithm parameters for block write */
360 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[index
],
361 sizeof(algo_params
[index
]), (uint8_t *)&algo_params
[index
]);
362 if (retval
!= ERROR_OK
)
365 /* Wait for next ping pong buffer to be ready */
367 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
368 if (retval
!= ERROR_OK
)
375 elapsed_ms
= timeval_ms() - start_ms
;
376 if (elapsed_ms
> 500)
380 /* If no error yet, wait for last buffer to finish */
381 if (retval
== ERROR_OK
) {
383 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
386 /* Regardless of errors, try to close down algo */
387 (void)cc26xx_quit(bank
);
392 static int cc26xx_probe(struct flash_bank
*bank
)
394 struct target
*target
= bank
->target
;
395 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
397 uint32_t sector_length
;
404 retval
= target_read_u32(target
, FCFG1_ICEPICK_ID
, &value
);
405 if (retval
!= ERROR_OK
)
407 cc26xx_bank
->icepick_id
= value
;
409 retval
= target_read_u32(target
, FCFG1_USER_ID
, &value
);
410 if (retval
!= ERROR_OK
)
412 cc26xx_bank
->user_id
= value
;
414 cc26xx_bank
->device_type
= cc26xx_device_type(cc26xx_bank
->icepick_id
,
415 cc26xx_bank
->user_id
);
417 sector_length
= cc26xx_sector_length(cc26xx_bank
->icepick_id
);
419 /* Set up appropriate flash helper algorithm */
420 switch (cc26xx_bank
->icepick_id
& ICEPICK_ID_MASK
) {
421 case CC26X0_ICEPICK_ID
:
422 case CC26X1_ICEPICK_ID
:
423 case CC13X0_ICEPICK_ID
:
424 /* Chameleon family device */
425 cc26xx_bank
->algo_code
= cc26x0_algo
;
426 cc26xx_bank
->algo_size
= sizeof(cc26x0_algo
);
427 cc26xx_bank
->algo_working_size
= CC26X0_WORKING_SIZE
;
428 cc26xx_bank
->buffer_addr
[0] = CC26X0_ALGO_BUFFER_0
;
429 cc26xx_bank
->buffer_addr
[1] = CC26X0_ALGO_BUFFER_1
;
430 cc26xx_bank
->params_addr
[0] = CC26X0_ALGO_PARAMS_0
;
431 cc26xx_bank
->params_addr
[1] = CC26X0_ALGO_PARAMS_1
;
432 max_sectors
= CC26X0_MAX_SECTORS
;
434 case CC13X2_CC26X2_ICEPICK_ID
:
436 /* Agama family device */
437 cc26xx_bank
->algo_code
= cc26x2_algo
;
438 cc26xx_bank
->algo_size
= sizeof(cc26x2_algo
);
439 cc26xx_bank
->algo_working_size
= CC26X2_WORKING_SIZE
;
440 cc26xx_bank
->buffer_addr
[0] = CC26X2_ALGO_BUFFER_0
;
441 cc26xx_bank
->buffer_addr
[1] = CC26X2_ALGO_BUFFER_1
;
442 cc26xx_bank
->params_addr
[0] = CC26X2_ALGO_PARAMS_0
;
443 cc26xx_bank
->params_addr
[1] = CC26X2_ALGO_PARAMS_1
;
444 max_sectors
= CC26X2_MAX_SECTORS
;
448 retval
= target_read_u32(target
, CC26XX_FLASH_SIZE_INFO
, &value
);
449 if (retval
!= ERROR_OK
)
451 num_sectors
= value
& 0xff;
452 if (num_sectors
> max_sectors
)
453 num_sectors
= max_sectors
;
455 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
459 bank
->base
= CC26XX_FLASH_BASE_ADDR
;
460 bank
->num_sectors
= num_sectors
;
461 bank
->size
= num_sectors
* sector_length
;
462 bank
->write_start_alignment
= 0;
463 bank
->write_end_alignment
= 0;
464 cc26xx_bank
->sector_length
= sector_length
;
466 for (int i
= 0; i
< num_sectors
; i
++) {
467 bank
->sectors
[i
].offset
= i
* sector_length
;
468 bank
->sectors
[i
].size
= sector_length
;
469 bank
->sectors
[i
].is_erased
= -1;
470 bank
->sectors
[i
].is_protected
= 0;
473 /* We've successfully determined the stats on the flash bank */
474 cc26xx_bank
->probed
= true;
476 /* If we fall through to here, then all went well */
481 static int cc26xx_auto_probe(struct flash_bank
*bank
)
483 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
485 int retval
= ERROR_OK
;
487 if (!cc26xx_bank
->probed
)
488 retval
= cc26xx_probe(bank
);
493 static int cc26xx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
495 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
498 switch (cc26xx_bank
->device_type
) {
516 device
= "Unrecognized";
520 command_print_sameline(cmd
,
521 "%s device: ICEPick ID 0x%08" PRIx32
", USER ID 0x%08" PRIx32
"\n",
522 device
, cc26xx_bank
->icepick_id
, cc26xx_bank
->user_id
);
527 const struct flash_driver cc26xx_flash
= {
529 .flash_bank_command
= cc26xx_flash_bank_command
,
530 .erase
= cc26xx_erase
,
531 .write
= cc26xx_write
,
532 .read
= default_flash_read
,
533 .probe
= cc26xx_probe
,
534 .auto_probe
= cc26xx_auto_probe
,
535 .erase_check
= default_flash_blank_check
,
537 .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)