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 (retval
!= ERROR_OK
)
55 /* Write the MERASE bit of the FMC register */
56 retval
= target_write_u32(target
, FMC_REGISTER_ADDR
, FMC_MERASE_VALUE
);
57 if (retval
!= ERROR_OK
)
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 (retval
!= ERROR_OK
)
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
, unsigned int first
,
112 struct target
*target
= bank
->target
;
115 long long elapsed_ms
;
119 int retval
= ERROR_OK
;
121 if (TARGET_HALTED
!= target
->state
) {
122 LOG_ERROR("Target not halted");
123 return ERROR_TARGET_NOT_HALTED
;
126 /* Do a mass erase if user requested all sectors of flash */
127 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
128 /* Request mass erase of flash */
129 return cc3220sf_mass_erase(bank
);
132 /* Erase requested sectors one by one */
133 for (unsigned int i
= first
; i
<= last
; i
++) {
135 /* Determine address of sector to erase */
136 address
= FLASH_BASE_ADDR
+ i
* FLASH_SECTOR_SIZE
;
138 /* Set starting address to erase */
139 retval
= target_write_u32(target
, FMA_REGISTER_ADDR
, address
);
140 if (retval
!= ERROR_OK
)
143 /* Write the ERASE bit of the FMC register */
144 retval
= target_write_u32(target
, FMC_REGISTER_ADDR
, FMC_ERASE_VALUE
);
145 if (retval
!= ERROR_OK
)
148 /* Poll the ERASE bit until the erase is complete */
150 start_ms
= timeval_ms();
152 retval
= target_read_u32(target
, FMC_REGISTER_ADDR
, &value
);
153 if (retval
!= ERROR_OK
)
156 if ((value
& FMC_ERASE_BIT
) == 0) {
157 /* Bit clears when mass erase is finished */
160 elapsed_ms
= timeval_ms() - start_ms
;
161 if (elapsed_ms
> 500)
163 if (elapsed_ms
> FLASH_TIMEOUT
)
169 /* Sector erase timed out waiting for confirmation */
177 static int cc3220sf_write(struct flash_bank
*bank
, const uint8_t *buffer
,
178 uint32_t offset
, uint32_t count
)
180 struct target
*target
= bank
->target
;
181 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
182 struct working_area
*algo_working_area
;
183 struct working_area
*buffer_working_area
;
184 struct reg_param reg_params
[3];
185 uint32_t algo_base_address
;
186 uint32_t algo_buffer_address
;
187 uint32_t algo_buffer_size
;
193 int retval
= ERROR_OK
;
195 if (TARGET_HALTED
!= target
->state
) {
196 LOG_ERROR("Target not halted");
197 return ERROR_TARGET_NOT_HALTED
;
200 /* Obtain working area to use for flash helper algorithm */
201 retval
= target_alloc_working_area(target
, sizeof(cc3220sf_algo
),
203 if (retval
!= ERROR_OK
)
206 /* Obtain working area to use for flash buffer */
207 retval
= target_alloc_working_area(target
,
208 target_get_working_area_avail(target
), &buffer_working_area
);
209 if (retval
!= ERROR_OK
) {
210 target_free_working_area(target
, algo_working_area
);
214 algo_base_address
= algo_working_area
->address
;
215 algo_buffer_address
= buffer_working_area
->address
;
216 algo_buffer_size
= buffer_working_area
->size
;
218 /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
219 /* (algo runs more efficiently if it operates on 32 words at a time) */
220 if (algo_buffer_size
> 0x80)
221 algo_buffer_size
&= ~0x7f;
223 /* Write flash helper algorithm into target memory */
224 retval
= target_write_buffer(target
, algo_base_address
,
225 sizeof(cc3220sf_algo
), cc3220sf_algo
);
226 if (retval
!= ERROR_OK
) {
227 target_free_working_area(target
, algo_working_area
);
228 target_free_working_area(target
, buffer_working_area
);
232 /* Initialize the ARMv7m specific info to run the algorithm */
233 cc3220sf_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
234 cc3220sf_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
236 /* Initialize register params for flash helper algorithm */
237 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
238 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
239 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
241 /* Prepare to write to flash */
242 address
= FLASH_BASE_ADDR
+ offset
;
245 /* The flash hardware can only write complete words to flash. If
246 * an unaligned address is passed in, we must do a read-modify-write
247 * on a word with enough bytes to align the rest of the buffer. And
248 * if less than a whole word remains at the end, we must also do a
249 * read-modify-write on a final word to finish up.
252 /* Do one word write to align address on 32-bit boundary if needed */
253 if (0 != (address
& 0x3)) {
256 /* Get starting offset for data to write (will be 1 to 3) */
257 uint32_t head_offset
= address
& 0x03;
259 /* Get the aligned address to write this first word to */
260 uint32_t head_address
= address
& 0xfffffffc;
262 /* Retrieve what is already in flash at the head address */
263 retval
= target_read_buffer(target
, head_address
, sizeof(head
), head
);
265 if (retval
== ERROR_OK
) {
266 /* Substitute in the new data to write */
267 while ((remaining
> 0) && (head_offset
< 4)) {
268 head
[head_offset
] = *buffer
;
276 if (retval
== ERROR_OK
) {
277 /* Helper parameters are passed in registers R0-R2 */
278 /* Set start of data buffer, address to write to, and word count */
279 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
280 buf_set_u32(reg_params
[1].value
, 0, 32, head_address
);
281 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
283 /* Write head value into buffer to flash */
284 retval
= target_write_buffer(target
, algo_buffer_address
,
288 if (retval
== ERROR_OK
) {
289 /* Execute the flash helper algorithm */
290 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
291 algo_base_address
, 0, FLASH_TIMEOUT
,
292 &cc3220sf_bank
->armv7m_info
);
293 if (retval
!= ERROR_OK
)
294 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
296 /* Check that the head value was written to flash */
297 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
300 LOG_ERROR("cc3220sf: Flash operation failed");
305 /* Check if there's data at end of buffer that isn't a full word */
306 uint32_t tail_count
= remaining
& 0x03;
307 /* Adjust remaining so it is a multiple of whole words */
308 remaining
-= tail_count
;
310 while ((retval
== ERROR_OK
) && (remaining
> 0)) {
311 /* Set start of data buffer and address to write to */
312 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
313 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
315 /* Download data to write into memory buffer */
316 if (remaining
>= algo_buffer_size
) {
317 /* Fill up buffer with data to flash */
318 retval
= target_write_buffer(target
, algo_buffer_address
,
319 algo_buffer_size
, buffer
);
320 if (retval
!= ERROR_OK
)
323 /* Count to write is in 32-bit words */
324 words
= algo_buffer_size
/ 4;
326 /* Bump variables to next data */
327 address
+= algo_buffer_size
;
328 buffer
+= algo_buffer_size
;
329 remaining
-= algo_buffer_size
;
331 /* Fill buffer with what's left of the data */
332 retval
= target_write_buffer(target
, algo_buffer_address
,
334 if (retval
!= ERROR_OK
)
337 /* Calculate the final word count to write */
338 words
= remaining
/ 4;
339 if (0 != (remaining
% 4))
342 /* Bump variables to any final data */
343 address
+= remaining
;
348 /* Set number of words to write */
349 buf_set_u32(reg_params
[2].value
, 0, 32, words
);
351 /* Execute the flash helper algorithm */
352 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
353 algo_base_address
, 0, FLASH_TIMEOUT
,
354 &cc3220sf_bank
->armv7m_info
);
355 if (retval
!= ERROR_OK
) {
356 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
360 /* Check that all words were written to flash */
361 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
364 LOG_ERROR("cc3220sf: Flash operation failed");
371 /* Do one word write for any final bytes less than a full word */
372 if ((retval
== ERROR_OK
) && (0 != tail_count
)) {
375 /* Set starting byte offset for data to write */
376 uint32_t tail_offset
= 0;
378 /* Retrieve what is already in flash at the tail address */
379 retval
= target_read_buffer(target
, address
, sizeof(tail
), tail
);
381 if (retval
== ERROR_OK
) {
382 /* Substitute in the new data to write */
383 while (tail_count
> 0) {
384 tail
[tail_offset
] = *buffer
;
391 if (retval
== ERROR_OK
) {
392 /* Set start of data buffer, address to write to, and word count */
393 buf_set_u32(reg_params
[0].value
, 0, 32, algo_buffer_address
);
394 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
395 buf_set_u32(reg_params
[2].value
, 0, 32, 1);
397 /* Write tail value into buffer to flash */
398 retval
= target_write_buffer(target
, algo_buffer_address
,
402 if (retval
== ERROR_OK
) {
403 /* Execute the flash helper algorithm */
404 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
405 algo_base_address
, 0, FLASH_TIMEOUT
,
406 &cc3220sf_bank
->armv7m_info
);
407 if (retval
!= ERROR_OK
)
408 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
410 /* Check that the tail was written to flash */
411 result
= buf_get_u32(reg_params
[2].value
, 0, 32);
414 LOG_ERROR("cc3220sf: Flash operation failed");
420 destroy_reg_param(®_params
[0]);
421 destroy_reg_param(®_params
[1]);
422 destroy_reg_param(®_params
[2]);
423 target_free_working_area(target
, algo_working_area
);
424 target_free_working_area(target
, buffer_working_area
);
429 static int cc3220sf_probe(struct flash_bank
*bank
)
431 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
435 unsigned int num_sectors
;
437 base
= FLASH_BASE_ADDR
;
438 size
= FLASH_NUM_SECTORS
* FLASH_SECTOR_SIZE
;
439 num_sectors
= FLASH_NUM_SECTORS
;
443 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
444 if (NULL
== bank
->sectors
)
449 bank
->write_start_alignment
= 0;
450 bank
->write_end_alignment
= 0;
451 bank
->num_sectors
= num_sectors
;
453 for (unsigned int i
= 0; i
< num_sectors
; i
++) {
454 bank
->sectors
[i
].offset
= i
* FLASH_SECTOR_SIZE
;
455 bank
->sectors
[i
].size
= FLASH_SECTOR_SIZE
;
456 bank
->sectors
[i
].is_erased
= -1;
457 bank
->sectors
[i
].is_protected
= 0;
460 /* We've successfully recorded the stats on this flash bank */
461 cc3220sf_bank
->probed
= true;
463 /* If we fall through to here, then all went well */
468 static int cc3220sf_auto_probe(struct flash_bank
*bank
)
470 struct cc3220sf_bank
*cc3220sf_bank
= bank
->driver_priv
;
472 int retval
= ERROR_OK
;
474 if (!cc3220sf_bank
->probed
)
475 retval
= cc3220sf_probe(bank
);
480 static int cc3220sf_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
482 command_print_sameline(cmd
, "CC3220SF with 1MB internal flash\n");
486 const struct flash_driver cc3220sf_flash
= {
488 .flash_bank_command
= cc3220sf_flash_bank_command
,
489 .erase
= cc3220sf_erase
,
490 .write
= cc3220sf_write
,
491 .read
= default_flash_read
,
492 .probe
= cc3220sf_probe
,
493 .auto_probe
= cc3220sf_auto_probe
,
494 .erase_check
= default_flash_blank_check
,
495 .info
= cc3220sf_info
,
496 .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)