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/time_support.h>
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
28 #define FLASH_TIMEOUT 5000
30 struct cc3220sf_bank
{
32 struct armv7m_algorithm armv7m_info
;
35 static int cc3220sf_mass_erase(struct flash_bank
*bank
)
37 struct target
*target
= bank
->target
;
43 int retval
= ERROR_OK
;
45 if (TARGET_HALTED
!= target
->state
) {
46 LOG_ERROR("Target not halted");
47 return ERROR_TARGET_NOT_HALTED
;
50 /* Set starting address to erase to zero */
51 retval
= target_write_u32(target
, FMA_REGISTER_ADDR
, 0);
52 if (ERROR_OK
!= retval
)
55 /* Write the MERASE bit of the FMC register */
56 retval
= target_write_u32(target
, FMC_REGISTER_ADDR
, FMC_MERASE_VALUE
);
57 if (ERROR_OK
!= retval
)
60 /* Poll the MERASE bit until the mass erase is complete */
62 start_ms
= timeval_ms();
64 retval
= target_read_u32(target
, FMC_REGISTER_ADDR
, &value
);
65 if (ERROR_OK
!= retval
)
68 if ((value
& FMC_MERASE_BIT
) == 0) {
69 /* Bit clears when mass erase is finished */
72 elapsed_ms
= timeval_ms() - start_ms
;
75 if (elapsed_ms
> FLASH_TIMEOUT
)
81 /* Mass erase timed out waiting for confirmation */
88 FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command
)
90 struct cc3220sf_bank
*cc3220sf_bank
;
93 return ERROR_COMMAND_SYNTAX_ERROR
;
95 cc3220sf_bank
= malloc(sizeof(struct cc3220sf_bank
));
96 if (NULL
== cc3220sf_bank
)
99 /* Initialize private flash information */
100 cc3220sf_bank
->probed
= false;
102 /* Finish initialization of flash bank */
103 bank
->driver_priv
= cc3220sf_bank
;
109 static int cc3220sf_erase(struct flash_bank
*bank
, int first
, int last
)
111 struct target
*target
= bank
->target
;
114 long long elapsed_ms
;
118 int retval
= ERROR_OK
;
120 if (TARGET_HALTED
!= target
->state
) {
121 LOG_ERROR("Target not halted");
122 return ERROR_TARGET_NOT_HALTED
;
125 /* Do a mass erase if user requested all sectors of flash */
126 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
127 /* Request mass erase of flash */
128 return cc3220sf_mass_erase(bank
);
131 /* Erase requested sectors one by one */
132 for (int i
= first
; i
<= last
; i
++) {
134 /* Determine address of sector to erase */
135 address
= FLASH_BASE_ADDR
+ i
* FLASH_SECTOR_SIZE
;
137 /* Set starting address to erase */
138 retval
= target_write_u32(target
, FMA_REGISTER_ADDR
, address
);
139 if (ERROR_OK
!= retval
)
142 /* Write the ERASE bit of the FMC register */
143 retval
= target_write_u32(target
, FMC_REGISTER_ADDR
, FMC_ERASE_VALUE
);
144 if (ERROR_OK
!= retval
)
147 /* Poll the ERASE bit until the erase is complete */
149 start_ms
= timeval_ms();
151 retval
= target_read_u32(target
, FMC_REGISTER_ADDR
, &value
);
152 if (ERROR_OK
!= retval
)
155 if ((value
& FMC_ERASE_BIT
) == 0) {
156 /* Bit clears when mass erase is finished */
159 elapsed_ms
= timeval_ms() - start_ms
;
160 if (elapsed_ms
> 500)
162 if (elapsed_ms
> FLASH_TIMEOUT
)
168 /* Sector erase timed out waiting for confirmation */
176 static int cc3220sf_protect(struct flash_bank
*bank
, int set
, int first
,
182 static int cc3220sf_write(struct flash_bank
*bank
, const uint8_t *buffer
,
183 uint32_t offset
, uint32_t count
)
185 struct target
*target
= bank
->target
;
186 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
187 struct working_area
*algo_working_area
;
188 struct working_area
*buffer_working_area
;
189 struct reg_param reg_params
[3];
190 uint32_t algo_base_address
;
191 uint32_t algo_buffer_address
;
192 uint32_t algo_buffer_size
;
198 int retval
= ERROR_OK
;
200 if (TARGET_HALTED
!= target
->state
) {
201 LOG_ERROR("Target not halted");
202 return ERROR_TARGET_NOT_HALTED
;
205 /* Obtain working area to use for flash helper algorithm */
206 retval
= target_alloc_working_area(target
, sizeof(cc3220sf_algo
),
208 if (ERROR_OK
!= retval
)
211 /* Obtain working area to use for flash buffer */
212 retval
= target_alloc_working_area(target
,
213 target_get_working_area_avail(target
), &buffer_working_area
);
214 if (ERROR_OK
!= retval
) {
215 target_free_working_area(target
, algo_working_area
);
219 algo_base_address
= algo_working_area
->address
;
220 algo_buffer_address
= buffer_working_area
->address
;
221 algo_buffer_size
= buffer_working_area
->size
;
223 /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
224 /* (algo runs more efficiently if it operates on 32 words at a time) */
225 if (algo_buffer_size
> 0x80)
226 algo_buffer_size
&= ~0x7f;
228 /* Write flash helper algorithm into target memory */
229 retval
= target_write_buffer(target
, algo_base_address
,
230 sizeof(cc3220sf_algo
), cc3220sf_algo
);
231 if (ERROR_OK
!= retval
) {
232 target_free_working_area(target
, algo_working_area
);
233 target_free_working_area(target
, buffer_working_area
);
237 /* Initialize the ARMv7m specific info to run the algorithm */
238 cc3220sf_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
239 cc3220sf_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
241 /* Initialize register params for flash helper algorithm */
242 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
243 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
244 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
246 /* Prepare to write to flash */
247 address
= FLASH_BASE_ADDR
+ offset
;
250 /* The flash hardware can only write complete words to flash. If
251 * an unaligned address is passed in, we must do a read-modify-write
252 * on a word with enough bytes to align the rest of the buffer. And
253 * if less than a whole word remains at the end, we must also do a
254 * read-modify-write on a final word to finish up.
257 /* Do one word write to align address on 32-bit boundary if needed */
258 if (0 != (address
& 0x3)) {
261 /* Get starting offset for data to write (will be 1 to 3) */
262 uint32_t head_offset
= address
& 0x03;
264 /* Get the aligned address to write this first word to */
265 uint32_t head_address
= address
& 0xfffffffc;
267 /* Retrieve what is already in flash at the head address */
268 retval
= target_read_buffer(target
, head_address
, sizeof(head
), head
);
270 if (ERROR_OK
== retval
) {
271 /* Substitute in the new data to write */
272 while ((remaining
> 0) && (head_offset
< 4)) {
273 head
[head_offset
] = *buffer
;
281 if (ERROR_OK
== retval
) {
282 /* Helper parameters are passed in registers R0-R2 */
283 /* Set start of data buffer, address to write to, and word count */
284 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
285 buf_set_u32(reg_params
[1].value
, 0, 32, head_address
);
286 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
288 /* Write head value into buffer to flash */
289 retval
= target_write_buffer(target
, algo_buffer_address
,
293 if (ERROR_OK
== retval
) {
294 /* Execute the flash helper algorithm */
295 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
296 algo_base_address
, 0, FLASH_TIMEOUT
,
297 &cc3220sf_bank
->armv7m_info
);
298 if (ERROR_OK
!= retval
)
299 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
301 /* Check that the head value was written to flash */
302 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
305 LOG_ERROR("cc3220sf: Flash operation failed");
310 /* Check if there's data at end of buffer that isn't a full word */
311 uint32_t tail_count
= remaining
& 0x03;
312 /* Adjust remaining so it is a multiple of whole words */
313 remaining
-= tail_count
;
315 while ((ERROR_OK
== retval
) && (remaining
> 0)) {
316 /* Set start of data buffer and address to write to */
317 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
318 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
320 /* Download data to write into memory buffer */
321 if (remaining
>= algo_buffer_size
) {
322 /* Fill up buffer with data to flash */
323 retval
= target_write_buffer(target
, algo_buffer_address
,
324 algo_buffer_size
, buffer
);
325 if (ERROR_OK
!= retval
)
328 /* Count to write is in 32-bit words */
329 words
= algo_buffer_size
/ 4;
331 /* Bump variables to next data */
332 address
+= algo_buffer_size
;
333 buffer
+= algo_buffer_size
;
334 remaining
-= algo_buffer_size
;
336 /* Fill buffer with what's left of the data */
337 retval
= target_write_buffer(target
, algo_buffer_address
,
339 if (ERROR_OK
!= retval
)
342 /* Calculate the final word count to write */
343 words
= remaining
/ 4;
344 if (0 != (remaining
% 4))
347 /* Bump variables to any final data */
348 address
+= remaining
;
353 /* Set number of words to write */
354 buf_set_u32(reg_params
[2].value
, 0, 32, words
);
356 /* Execute the flash helper algorithm */
357 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
358 algo_base_address
, 0, FLASH_TIMEOUT
,
359 &cc3220sf_bank
->armv7m_info
);
360 if (ERROR_OK
!= retval
) {
361 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
365 /* Check that all words were written to flash */
366 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
369 LOG_ERROR("cc3220sf: Flash operation failed");
374 /* Do one word write for any final bytes less than a full word */
375 if ((ERROR_OK
== retval
) && (0 != tail_count
)) {
378 /* Set starting byte offset for data to write */
379 uint32_t tail_offset
= 0;
381 /* Retrieve what is already in flash at the tail address */
382 retval
= target_read_buffer(target
, address
, sizeof(tail
), tail
);
384 if (ERROR_OK
== retval
) {
385 /* Substitute in the new data to write */
386 while (tail_count
> 0) {
387 tail
[tail_offset
] = *buffer
;
394 if (ERROR_OK
== retval
) {
395 /* Set start of data buffer, address to write to, and word count */
396 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
397 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
398 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
400 /* Write tail value into buffer to flash */
401 retval
= target_write_buffer(target
, algo_buffer_address
,
405 if (ERROR_OK
== retval
) {
406 /* Execute the flash helper algorithm */
407 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
408 algo_base_address
, 0, FLASH_TIMEOUT
,
409 &cc3220sf_bank
->armv7m_info
);
410 if (ERROR_OK
!= retval
)
411 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
413 /* Check that the tail was written to flash */
414 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
417 LOG_ERROR("cc3220sf: Flash operation failed");
423 destroy_reg_param(®_params
[0]);
424 destroy_reg_param(®_params
[1]);
425 destroy_reg_param(®_params
[2]);
426 target_free_working_area(target
, algo_working_area
);
427 target_free_working_area(target
, buffer_working_area
);
432 static int cc3220sf_probe(struct flash_bank
*bank
)
434 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
441 bank_id
= bank
->bank_number
;
444 base
= FLASH_BASE_ADDR
;
445 size
= FLASH_NUM_SECTORS
* FLASH_SECTOR_SIZE
;
446 num_sectors
= FLASH_NUM_SECTORS
;
448 /* Invalid bank number somehow */
452 if (NULL
!= bank
->sectors
) {
454 bank
->sectors
= NULL
;
457 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
458 if (NULL
== bank
->sectors
)
463 bank
->write_start_alignment
= 0;
464 bank
->write_end_alignment
= 0;
465 bank
->num_sectors
= num_sectors
;
467 for (int i
= 0; i
< num_sectors
; i
++) {
468 bank
->sectors
[i
].offset
= i
* FLASH_SECTOR_SIZE
;
469 bank
->sectors
[i
].size
= FLASH_SECTOR_SIZE
;
470 bank
->sectors
[i
].is_erased
= -1;
471 bank
->sectors
[i
].is_protected
= 0;
474 /* We've successfully recorded the stats on this flash bank */
475 cc3220sf_bank
->probed
= true;
477 /* If we fall through to here, then all went well */
482 static int cc3220sf_auto_probe(struct flash_bank
*bank
)
484 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
486 int retval
= ERROR_OK
;
488 if (0 != bank
->bank_number
) {
489 /* Invalid bank number somehow */
493 if (!cc3220sf_bank
->probed
)
494 retval
= cc3220sf_probe(bank
);
499 static int cc3220sf_protect_check(struct flash_bank
*bank
)
504 static int cc3220sf_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
508 printed
= snprintf(buf
, buf_size
, "CC3220SF with 1MB internal flash\n");
510 if (printed
>= buf_size
)
511 return ERROR_BUF_TOO_SMALL
;
516 struct flash_driver cc3220sf_flash
= {
518 .flash_bank_command
= cc3220sf_flash_bank_command
,
519 .erase
= cc3220sf_erase
,
520 .protect
= cc3220sf_protect
,
521 .write
= cc3220sf_write
,
522 .read
= default_flash_read
,
523 .probe
= cc3220sf_probe
,
524 .auto_probe
= cc3220sf_auto_probe
,
525 .erase_check
= default_flash_blank_check
,
526 .protect_check
= cc3220sf_protect_check
,
527 .info
= cc3220sf_info
,
528 .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)