1 /***************************************************************************
2 * Copyright (C) 2017 by Texas Instruments, Inc. *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
24 #include <helper/binarybuffer.h>
25 #include <helper/time_support.h>
26 #include <target/algorithm.h>
27 #include <target/armv7m.h>
28 #include <target/image.h>
30 #define FLASH_TIMEOUT 8000
33 const char *family_name
;
37 uint32_t sector_length
;
39 struct working_area
*working_area
;
40 struct armv7m_algorithm armv7m_info
;
41 const uint8_t *algo_code
;
43 uint32_t algo_working_size
;
44 uint32_t buffer_addr
[2];
45 uint32_t params_addr
[2];
48 static int cc26xx_auto_probe(struct flash_bank
*bank
);
50 static uint32_t cc26xx_device_type(uint32_t icepick_id
, uint32_t user_id
)
52 uint32_t device_type
= 0;
54 switch (icepick_id
& ICEPICK_ID_MASK
) {
55 case CC26X0_ICEPICK_ID
:
56 device_type
= CC26X0_TYPE
;
58 case CC26X1_ICEPICK_ID
:
59 device_type
= CC26X1_TYPE
;
61 case CC13X0_ICEPICK_ID
:
62 device_type
= CC13X0_TYPE
;
64 case CC13X2_CC26X2_ICEPICK_ID
:
66 if ((user_id
& USER_ID_CC13_MASK
) != 0)
67 device_type
= CC13X2_TYPE
;
69 device_type
= CC26X2_TYPE
;
76 static uint32_t cc26xx_sector_length(uint32_t icepick_id
)
78 uint32_t sector_length
;
80 switch (icepick_id
& ICEPICK_ID_MASK
) {
81 case CC26X0_ICEPICK_ID
:
82 case CC26X1_ICEPICK_ID
:
83 case CC13X0_ICEPICK_ID
:
84 /* Chameleon family device */
85 sector_length
= CC26X0_SECTOR_LENGTH
;
87 case CC13X2_CC26X2_ICEPICK_ID
:
89 /* Agama family device */
90 sector_length
= CC26X2_SECTOR_LENGTH
;
97 static int cc26xx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
99 struct target
*target
= bank
->target
;
100 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
102 uint32_t status_addr
= params_addr
+ CC26XX_STATUS_OFFSET
;
103 uint32_t status
= CC26XX_BUFFER_FULL
;
105 long long elapsed_ms
;
107 int retval
= ERROR_OK
;
109 start_ms
= timeval_ms();
110 while (CC26XX_BUFFER_FULL
== status
) {
111 retval
= target_read_u32(target
, status_addr
, &status
);
112 if (ERROR_OK
!= retval
)
115 elapsed_ms
= timeval_ms() - start_ms
;
116 if (elapsed_ms
> 500)
118 if (elapsed_ms
> FLASH_TIMEOUT
)
122 if (CC26XX_BUFFER_EMPTY
!= status
) {
123 LOG_ERROR("%s: Flash operation failed", cc26xx_bank
->family_name
);
130 static int cc26xx_init(struct flash_bank
*bank
)
132 struct target
*target
= bank
->target
;
133 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
137 /* Make sure we've probed the flash to get the device and size */
138 retval
= cc26xx_auto_probe(bank
);
139 if (ERROR_OK
!= retval
)
142 /* Check for working area to use for flash helper algorithm */
143 if (NULL
!= cc26xx_bank
->working_area
)
144 target_free_working_area(target
, cc26xx_bank
->working_area
);
145 retval
= target_alloc_working_area(target
, cc26xx_bank
->algo_working_size
,
146 &cc26xx_bank
->working_area
);
147 if (ERROR_OK
!= retval
)
150 /* Confirm the defined working address is the area we need to use */
151 if (CC26XX_ALGO_BASE_ADDRESS
!= cc26xx_bank
->working_area
->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 (ERROR_OK
!= retval
) {
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
);
164 /* Initialize the ARMv7 specific info to run the algorithm */
165 cc26xx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
166 cc26xx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
168 /* Begin executing the flash helper algorithm */
169 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
170 CC26XX_ALGO_BASE_ADDRESS
, 0, &cc26xx_bank
->armv7m_info
);
171 if (ERROR_OK
!= retval
) {
172 LOG_ERROR("%s: Failed to start flash helper algorithm",
173 cc26xx_bank
->family_name
);
174 target_free_working_area(target
, cc26xx_bank
->working_area
);
179 * At this point, the algorithm is running on the target and
180 * ready to receive commands and data to flash the target
186 static int cc26xx_quit(struct flash_bank
*bank
)
188 struct target
*target
= bank
->target
;
189 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
193 /* Regardless of the algo's status, attempt to halt the target */
194 (void)target_halt(target
);
196 /* Now confirm target halted and clean up from flash helper algorithm */
197 retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0, FLASH_TIMEOUT
,
198 &cc26xx_bank
->armv7m_info
);
200 target_free_working_area(target
, cc26xx_bank
->working_area
);
201 cc26xx_bank
->working_area
= NULL
;
206 static int cc26xx_mass_erase(struct flash_bank
*bank
)
208 struct target
*target
= bank
->target
;
209 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
210 struct cc26xx_algo_params algo_params
;
214 if (TARGET_HALTED
!= target
->state
) {
215 LOG_ERROR("Target not halted");
216 return ERROR_TARGET_NOT_HALTED
;
219 retval
= cc26xx_init(bank
);
220 if (ERROR_OK
!= retval
)
223 /* Initialize algorithm parameters */
224 buf_set_u32(algo_params
.address
, 0, 32, 0);
225 buf_set_u32(algo_params
.length
, 0, 32, 4);
226 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_ALL
);
227 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
229 /* Issue flash helper algorithm parameters for mass erase */
230 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
231 sizeof(algo_params
), (uint8_t *)&algo_params
);
233 /* Wait for command to complete */
234 if (ERROR_OK
== retval
)
235 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
237 /* Regardless of errors, try to close down algo */
238 (void)cc26xx_quit(bank
);
243 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command
)
245 struct cc26xx_bank
*cc26xx_bank
;
248 return ERROR_COMMAND_SYNTAX_ERROR
;
250 cc26xx_bank
= malloc(sizeof(struct cc26xx_bank
));
251 if (NULL
== cc26xx_bank
)
254 /* Initialize private flash information */
255 memset((void *)cc26xx_bank
, 0x00, sizeof(struct cc26xx_bank
));
256 cc26xx_bank
->family_name
= "cc26xx";
257 cc26xx_bank
->device_type
= CC26XX_NO_TYPE
;
258 cc26xx_bank
->sector_length
= 0x1000;
260 /* Finish initialization of bank */
261 bank
->driver_priv
= cc26xx_bank
;
267 static int cc26xx_erase(struct flash_bank
*bank
, int first
, int last
)
269 struct target
*target
= bank
->target
;
270 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
271 struct cc26xx_algo_params algo_params
;
277 if (TARGET_HALTED
!= target
->state
) {
278 LOG_ERROR("Target not halted");
279 return ERROR_TARGET_NOT_HALTED
;
282 /* Do a mass erase if user requested all sectors of flash */
283 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
284 /* Request mass erase of flash */
285 return cc26xx_mass_erase(bank
);
288 address
= first
* cc26xx_bank
->sector_length
;
289 length
= (last
- first
+ 1) * cc26xx_bank
->sector_length
;
291 retval
= cc26xx_init(bank
);
292 if (ERROR_OK
!= retval
)
295 /* Set up algorithm parameters for erase command */
296 buf_set_u32(algo_params
.address
, 0, 32, address
);
297 buf_set_u32(algo_params
.length
, 0, 32, length
);
298 buf_set_u32(algo_params
.command
, 0, 32, CC26XX_CMD_ERASE_SECTORS
);
299 buf_set_u32(algo_params
.status
, 0, 32, CC26XX_BUFFER_FULL
);
301 /* Issue flash helper algorithm parameters for erase */
302 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[0],
303 sizeof(algo_params
), (uint8_t *)&algo_params
);
305 /* If no error, wait for erase to finish */
306 if (ERROR_OK
== retval
)
307 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[0]);
309 /* Regardless of errors, try to close down algo */
310 (void)cc26xx_quit(bank
);
315 static int cc26xx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
316 uint32_t offset
, uint32_t count
)
318 struct target
*target
= bank
->target
;
319 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
320 struct cc26xx_algo_params algo_params
[2];
323 long long elapsed_ms
;
329 if (TARGET_HALTED
!= target
->state
) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED
;
334 retval
= cc26xx_init(bank
);
335 if (ERROR_OK
!= retval
)
338 /* Initialize algorithm parameters to default values */
339 buf_set_u32(algo_params
[0].command
, 0, 32, CC26XX_CMD_PROGRAM
);
340 buf_set_u32(algo_params
[1].command
, 0, 32, CC26XX_CMD_PROGRAM
);
342 /* Write requested data, ping-ponging between two buffers */
344 start_ms
= timeval_ms();
345 address
= bank
->base
+ offset
;
348 if (count
> cc26xx_bank
->sector_length
)
349 size
= cc26xx_bank
->sector_length
;
353 /* Put next block of data to flash into buffer */
354 retval
= target_write_buffer(target
, cc26xx_bank
->buffer_addr
[index
],
356 if (ERROR_OK
!= retval
) {
357 LOG_ERROR("Unable to write data to target memory");
361 /* Update algo parameters for next block */
362 buf_set_u32(algo_params
[index
].address
, 0, 32, address
);
363 buf_set_u32(algo_params
[index
].length
, 0, 32, size
);
364 buf_set_u32(algo_params
[index
].status
, 0, 32, CC26XX_BUFFER_FULL
);
366 /* Issue flash helper algorithm parameters for block write */
367 retval
= target_write_buffer(target
, cc26xx_bank
->params_addr
[index
],
368 sizeof(algo_params
[index
]), (uint8_t *)&algo_params
[index
]);
369 if (ERROR_OK
!= retval
)
372 /* Wait for next ping pong buffer to be ready */
374 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
375 if (ERROR_OK
!= retval
)
382 elapsed_ms
= timeval_ms() - start_ms
;
383 if (elapsed_ms
> 500)
387 /* If no error yet, wait for last buffer to finish */
388 if (ERROR_OK
== retval
) {
390 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
393 /* Regardless of errors, try to close down algo */
394 (void)cc26xx_quit(bank
);
399 static int cc26xx_probe(struct flash_bank
*bank
)
401 struct target
*target
= bank
->target
;
402 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
404 uint32_t sector_length
;
411 retval
= target_read_u32(target
, FCFG1_ICEPICK_ID
, &value
);
412 if (ERROR_OK
!= retval
)
414 cc26xx_bank
->icepick_id
= value
;
416 retval
= target_read_u32(target
, FCFG1_USER_ID
, &value
);
417 if (ERROR_OK
!= retval
)
419 cc26xx_bank
->user_id
= value
;
421 cc26xx_bank
->device_type
= cc26xx_device_type(cc26xx_bank
->icepick_id
,
422 cc26xx_bank
->user_id
);
424 sector_length
= cc26xx_sector_length(cc26xx_bank
->icepick_id
);
426 /* Set up appropriate flash helper algorithm */
427 switch (cc26xx_bank
->icepick_id
& ICEPICK_ID_MASK
) {
428 case CC26X0_ICEPICK_ID
:
429 case CC26X1_ICEPICK_ID
:
430 case CC13X0_ICEPICK_ID
:
431 /* Chameleon family device */
432 cc26xx_bank
->algo_code
= cc26x0_algo
;
433 cc26xx_bank
->algo_size
= sizeof(cc26x0_algo
);
434 cc26xx_bank
->algo_working_size
= CC26X0_WORKING_SIZE
;
435 cc26xx_bank
->buffer_addr
[0] = CC26X0_ALGO_BUFFER_0
;
436 cc26xx_bank
->buffer_addr
[1] = CC26X0_ALGO_BUFFER_1
;
437 cc26xx_bank
->params_addr
[0] = CC26X0_ALGO_PARAMS_0
;
438 cc26xx_bank
->params_addr
[1] = CC26X0_ALGO_PARAMS_1
;
439 max_sectors
= CC26X0_MAX_SECTORS
;
441 case CC13X2_CC26X2_ICEPICK_ID
:
443 /* Agama family device */
444 cc26xx_bank
->algo_code
= cc26x2_algo
;
445 cc26xx_bank
->algo_size
= sizeof(cc26x2_algo
);
446 cc26xx_bank
->algo_working_size
= CC26X2_WORKING_SIZE
;
447 cc26xx_bank
->buffer_addr
[0] = CC26X2_ALGO_BUFFER_0
;
448 cc26xx_bank
->buffer_addr
[1] = CC26X2_ALGO_BUFFER_1
;
449 cc26xx_bank
->params_addr
[0] = CC26X2_ALGO_PARAMS_0
;
450 cc26xx_bank
->params_addr
[1] = CC26X2_ALGO_PARAMS_1
;
451 max_sectors
= CC26X2_MAX_SECTORS
;
455 retval
= target_read_u32(target
, CC26XX_FLASH_SIZE_INFO
, &value
);
456 if (ERROR_OK
!= retval
)
458 num_sectors
= value
& 0xff;
459 if (num_sectors
> max_sectors
)
460 num_sectors
= max_sectors
;
462 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
463 if (NULL
== bank
->sectors
)
466 bank
->base
= CC26XX_FLASH_BASE_ADDR
;
467 bank
->num_sectors
= num_sectors
;
468 bank
->size
= num_sectors
* sector_length
;
469 bank
->write_start_alignment
= 0;
470 bank
->write_end_alignment
= 0;
471 cc26xx_bank
->sector_length
= sector_length
;
473 for (int i
= 0; i
< num_sectors
; i
++) {
474 bank
->sectors
[i
].offset
= i
* sector_length
;
475 bank
->sectors
[i
].size
= sector_length
;
476 bank
->sectors
[i
].is_erased
= -1;
477 bank
->sectors
[i
].is_protected
= 0;
480 /* We've successfully determined the stats on the flash bank */
481 cc26xx_bank
->probed
= true;
483 /* If we fall through to here, then all went well */
488 static int cc26xx_auto_probe(struct flash_bank
*bank
)
490 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
492 int retval
= ERROR_OK
;
494 if (!cc26xx_bank
->probed
)
495 retval
= cc26xx_probe(bank
);
500 static int cc26xx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
502 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
506 switch (cc26xx_bank
->device_type
) {
524 device
= "Unrecognized";
528 printed
= snprintf(buf
, buf_size
,
529 "%s device: ICEPick ID 0x%08x, USER ID 0x%08x\n",
530 device
, cc26xx_bank
->icepick_id
, cc26xx_bank
->user_id
);
532 if (printed
>= buf_size
)
533 return ERROR_BUF_TOO_SMALL
;
538 const struct flash_driver cc26xx_flash
= {
540 .flash_bank_command
= cc26xx_flash_bank_command
,
541 .erase
= cc26xx_erase
,
542 .write
= cc26xx_write
,
543 .read
= default_flash_read
,
544 .probe
= cc26xx_probe
,
545 .auto_probe
= cc26xx_auto_probe
,
546 .erase_check
= default_flash_blank_check
,
548 .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)