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_write(struct flash_bank
*bank
, const uint8_t *buffer
,
177 uint32_t offset
, uint32_t count
)
179 struct target
*target
= bank
->target
;
180 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
181 struct working_area
*algo_working_area
;
182 struct working_area
*buffer_working_area
;
183 struct reg_param reg_params
[3];
184 uint32_t algo_base_address
;
185 uint32_t algo_buffer_address
;
186 uint32_t algo_buffer_size
;
192 int retval
= ERROR_OK
;
194 if (TARGET_HALTED
!= target
->state
) {
195 LOG_ERROR("Target not halted");
196 return ERROR_TARGET_NOT_HALTED
;
199 /* Obtain working area to use for flash helper algorithm */
200 retval
= target_alloc_working_area(target
, sizeof(cc3220sf_algo
),
202 if (ERROR_OK
!= retval
)
205 /* Obtain working area to use for flash buffer */
206 retval
= target_alloc_working_area(target
,
207 target_get_working_area_avail(target
), &buffer_working_area
);
208 if (ERROR_OK
!= retval
) {
209 target_free_working_area(target
, algo_working_area
);
213 algo_base_address
= algo_working_area
->address
;
214 algo_buffer_address
= buffer_working_area
->address
;
215 algo_buffer_size
= buffer_working_area
->size
;
217 /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
218 /* (algo runs more efficiently if it operates on 32 words at a time) */
219 if (algo_buffer_size
> 0x80)
220 algo_buffer_size
&= ~0x7f;
222 /* Write flash helper algorithm into target memory */
223 retval
= target_write_buffer(target
, algo_base_address
,
224 sizeof(cc3220sf_algo
), cc3220sf_algo
);
225 if (ERROR_OK
!= retval
) {
226 target_free_working_area(target
, algo_working_area
);
227 target_free_working_area(target
, buffer_working_area
);
231 /* Initialize the ARMv7m specific info to run the algorithm */
232 cc3220sf_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
233 cc3220sf_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
235 /* Initialize register params for flash helper algorithm */
236 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
237 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
238 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
240 /* Prepare to write to flash */
241 address
= FLASH_BASE_ADDR
+ offset
;
244 /* The flash hardware can only write complete words to flash. If
245 * an unaligned address is passed in, we must do a read-modify-write
246 * on a word with enough bytes to align the rest of the buffer. And
247 * if less than a whole word remains at the end, we must also do a
248 * read-modify-write on a final word to finish up.
251 /* Do one word write to align address on 32-bit boundary if needed */
252 if (0 != (address
& 0x3)) {
255 /* Get starting offset for data to write (will be 1 to 3) */
256 uint32_t head_offset
= address
& 0x03;
258 /* Get the aligned address to write this first word to */
259 uint32_t head_address
= address
& 0xfffffffc;
261 /* Retrieve what is already in flash at the head address */
262 retval
= target_read_buffer(target
, head_address
, sizeof(head
), head
);
264 if (ERROR_OK
== retval
) {
265 /* Substitute in the new data to write */
266 while ((remaining
> 0) && (head_offset
< 4)) {
267 head
[head_offset
] = *buffer
;
275 if (ERROR_OK
== retval
) {
276 /* Helper parameters are passed in registers R0-R2 */
277 /* Set start of data buffer, address to write to, and word count */
278 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
279 buf_set_u32(reg_params
[1].value
, 0, 32, head_address
);
280 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
282 /* Write head value into buffer to flash */
283 retval
= target_write_buffer(target
, algo_buffer_address
,
287 if (ERROR_OK
== retval
) {
288 /* Execute the flash helper algorithm */
289 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
290 algo_base_address
, 0, FLASH_TIMEOUT
,
291 &cc3220sf_bank
->armv7m_info
);
292 if (ERROR_OK
!= retval
)
293 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
295 /* Check that the head value was written to flash */
296 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
299 LOG_ERROR("cc3220sf: Flash operation failed");
304 /* Check if there's data at end of buffer that isn't a full word */
305 uint32_t tail_count
= remaining
& 0x03;
306 /* Adjust remaining so it is a multiple of whole words */
307 remaining
-= tail_count
;
309 while ((ERROR_OK
== retval
) && (remaining
> 0)) {
310 /* Set start of data buffer and address to write to */
311 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
312 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
314 /* Download data to write into memory buffer */
315 if (remaining
>= algo_buffer_size
) {
316 /* Fill up buffer with data to flash */
317 retval
= target_write_buffer(target
, algo_buffer_address
,
318 algo_buffer_size
, buffer
);
319 if (ERROR_OK
!= retval
)
322 /* Count to write is in 32-bit words */
323 words
= algo_buffer_size
/ 4;
325 /* Bump variables to next data */
326 address
+= algo_buffer_size
;
327 buffer
+= algo_buffer_size
;
328 remaining
-= algo_buffer_size
;
330 /* Fill buffer with what's left of the data */
331 retval
= target_write_buffer(target
, algo_buffer_address
,
333 if (ERROR_OK
!= retval
)
336 /* Calculate the final word count to write */
337 words
= remaining
/ 4;
338 if (0 != (remaining
% 4))
341 /* Bump variables to any final data */
342 address
+= remaining
;
347 /* Set number of words to write */
348 buf_set_u32(reg_params
[2].value
, 0, 32, words
);
350 /* Execute the flash helper algorithm */
351 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
352 algo_base_address
, 0, FLASH_TIMEOUT
,
353 &cc3220sf_bank
->armv7m_info
);
354 if (ERROR_OK
!= retval
) {
355 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
359 /* Check that all words were written to flash */
360 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
363 LOG_ERROR("cc3220sf: Flash operation failed");
370 /* Do one word write for any final bytes less than a full word */
371 if ((ERROR_OK
== retval
) && (0 != tail_count
)) {
374 /* Set starting byte offset for data to write */
375 uint32_t tail_offset
= 0;
377 /* Retrieve what is already in flash at the tail address */
378 retval
= target_read_buffer(target
, address
, sizeof(tail
), tail
);
380 if (ERROR_OK
== retval
) {
381 /* Substitute in the new data to write */
382 while (tail_count
> 0) {
383 tail
[tail_offset
] = *buffer
;
390 if (ERROR_OK
== retval
) {
391 /* Set start of data buffer, address to write to, and word count */
392 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
393 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
394 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
396 /* Write tail value into buffer to flash */
397 retval
= target_write_buffer(target
, algo_buffer_address
,
401 if (ERROR_OK
== retval
) {
402 /* Execute the flash helper algorithm */
403 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
404 algo_base_address
, 0, FLASH_TIMEOUT
,
405 &cc3220sf_bank
->armv7m_info
);
406 if (ERROR_OK
!= retval
)
407 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
409 /* Check that the tail was written to flash */
410 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
413 LOG_ERROR("cc3220sf: Flash operation failed");
419 destroy_reg_param(®_params
[0]);
420 destroy_reg_param(®_params
[1]);
421 destroy_reg_param(®_params
[2]);
422 target_free_working_area(target
, algo_working_area
);
423 target_free_working_area(target
, buffer_working_area
);
428 static int cc3220sf_probe(struct flash_bank
*bank
)
430 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
436 base
= FLASH_BASE_ADDR
;
437 size
= FLASH_NUM_SECTORS
* FLASH_SECTOR_SIZE
;
438 num_sectors
= FLASH_NUM_SECTORS
;
440 if (NULL
!= bank
->sectors
) {
442 bank
->sectors
= NULL
;
445 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
446 if (NULL
== bank
->sectors
)
451 bank
->write_start_alignment
= 0;
452 bank
->write_end_alignment
= 0;
453 bank
->num_sectors
= num_sectors
;
455 for (int i
= 0; i
< num_sectors
; i
++) {
456 bank
->sectors
[i
].offset
= i
* FLASH_SECTOR_SIZE
;
457 bank
->sectors
[i
].size
= FLASH_SECTOR_SIZE
;
458 bank
->sectors
[i
].is_erased
= -1;
459 bank
->sectors
[i
].is_protected
= 0;
462 /* We've successfully recorded the stats on this flash bank */
463 cc3220sf_bank
->probed
= true;
465 /* If we fall through to here, then all went well */
470 static int cc3220sf_auto_probe(struct flash_bank
*bank
)
472 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
474 int retval
= ERROR_OK
;
476 if (!cc3220sf_bank
->probed
)
477 retval
= cc3220sf_probe(bank
);
482 static int cc3220sf_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
486 printed
= snprintf(buf
, buf_size
, "CC3220SF with 1MB internal flash\n");
488 if (printed
>= buf_size
)
489 return ERROR_BUF_TOO_SMALL
;
494 const struct flash_driver cc3220sf_flash
= {
496 .flash_bank_command
= cc3220sf_flash_bank_command
,
497 .erase
= cc3220sf_erase
,
498 .write
= cc3220sf_write
,
499 .read
= default_flash_read
,
500 .probe
= cc3220sf_probe
,
501 .auto_probe
= cc3220sf_auto_probe
,
502 .erase_check
= default_flash_blank_check
,
503 .info
= cc3220sf_info
,
504 .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)