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,