OpenOCD
cc3220sf.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2017 by Texas Instruments, Inc. *
5  ***************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "imp.h"
12 #include "cc3220sf.h"
13 #include <helper/binarybuffer.h>
14 #include <helper/time_support.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
17 
18 #define FLASH_TIMEOUT 5000
19 
20 struct cc3220sf_bank {
21  bool probed;
23 };
24 
25 /* Flash helper algorithm for CC3220SF */
26 static const uint8_t cc3220sf_algo[] = {
27 #include "../../../contrib/loaders/flash/cc3220sf/cc3220sf.inc"
28 };
29 
30 static int cc3220sf_mass_erase(struct flash_bank *bank)
31 {
32  struct target *target = bank->target;
33  bool done;
34  long long start_ms;
35  long long elapsed_ms;
36  uint32_t value;
37 
38  int retval = ERROR_OK;
39 
40  if (target->state != TARGET_HALTED) {
41  LOG_ERROR("Target not halted");
43  }
44 
45  /* Set starting address to erase to zero */
47  if (retval != ERROR_OK)
48  return retval;
49 
50  /* Write the MERASE bit of the FMC register */
52  if (retval != ERROR_OK)
53  return retval;
54 
55  /* Poll the MERASE bit until the mass erase is complete */
56  done = false;
57  start_ms = timeval_ms();
58  while (!done) {
59  retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
60  if (retval != ERROR_OK)
61  return retval;
62 
63  if ((value & FMC_MERASE_BIT) == 0) {
64  /* Bit clears when mass erase is finished */
65  done = true;
66  } else {
67  elapsed_ms = timeval_ms() - start_ms;
68  if (elapsed_ms > 500)
69  keep_alive();
70  if (elapsed_ms > FLASH_TIMEOUT)
71  break;
72  }
73  }
74 
75  if (!done) {
76  /* Mass erase timed out waiting for confirmation */
77  return ERROR_FAIL;
78  }
79 
80  return retval;
81 }
82 
83 FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
84 {
86 
87  if (CMD_ARGC < 6)
89 
90  cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank));
91  if (!cc3220sf_bank)
92  return ERROR_FAIL;
93 
94  /* Initialize private flash information */
95  cc3220sf_bank->probed = false;
96 
97  /* Finish initialization of flash bank */
98  bank->driver_priv = cc3220sf_bank;
99 
100  return ERROR_OK;
101 }
102 
103 static int cc3220sf_erase(struct flash_bank *bank, unsigned int first,
104  unsigned int last)
105 {
106  struct target *target = bank->target;
107  bool done;
108  long long start_ms;
109  long long elapsed_ms;
110  uint32_t address;
111  uint32_t value;
112 
113  int retval = ERROR_OK;
114 
115  if (target->state != TARGET_HALTED) {
116  LOG_ERROR("Target not halted");
118  }
119 
120  /* Do a mass erase if user requested all sectors of flash */
121  if ((first == 0) && (last == (bank->num_sectors - 1))) {
122  /* Request mass erase of flash */
123  return cc3220sf_mass_erase(bank);
124  }
125 
126  /* Erase requested sectors one by one */
127  for (unsigned int i = first; i <= last; i++) {
128 
129  /* Determine address of sector to erase */
130  address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE;
131 
132  /* Set starting address to erase */
133  retval = target_write_u32(target, FMA_REGISTER_ADDR, address);
134  if (retval != ERROR_OK)
135  return retval;
136 
137  /* Write the ERASE bit of the FMC register */
139  if (retval != ERROR_OK)
140  return retval;
141 
142  /* Poll the ERASE bit until the erase is complete */
143  done = false;
144  start_ms = timeval_ms();
145  while (!done) {
146  retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
147  if (retval != ERROR_OK)
148  return retval;
149 
150  if ((value & FMC_ERASE_BIT) == 0) {
151  /* Bit clears when mass erase is finished */
152  done = true;
153  } else {
154  elapsed_ms = timeval_ms() - start_ms;
155  if (elapsed_ms > 500)
156  keep_alive();
157  if (elapsed_ms > FLASH_TIMEOUT)
158  break;
159  }
160  }
161 
162  if (!done) {
163  /* Sector erase timed out waiting for confirmation */
164  return ERROR_FAIL;
165  }
166  }
167 
168  return retval;
169 }
170 
171 static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
172  uint32_t offset, uint32_t count)
173 {
174  struct target *target = bank->target;
175  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
176  struct working_area *algo_working_area;
177  struct working_area *buffer_working_area;
178  struct reg_param reg_params[3];
179  uint32_t algo_base_address;
180  uint32_t algo_buffer_address;
181  uint32_t algo_buffer_size;
182  uint32_t address;
183  uint32_t remaining;
184  uint32_t words;
185  uint32_t result;
186 
187  int retval = ERROR_OK;
188 
189  if (target->state != TARGET_HALTED) {
190  LOG_ERROR("Target not halted");
192  }
193 
194  /* Obtain working area to use for flash helper algorithm */
196  &algo_working_area);
197  if (retval != ERROR_OK)
198  return retval;
199 
200  /* Obtain working area to use for flash buffer */
202  target_get_working_area_avail(target), &buffer_working_area);
203  if (retval != ERROR_OK) {
204  target_free_working_area(target, algo_working_area);
205  return retval;
206  }
207 
208  algo_base_address = algo_working_area->address;
209  algo_buffer_address = buffer_working_area->address;
210  algo_buffer_size = buffer_working_area->size;
211 
212  /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
213  /* (algo runs more efficiently if it operates on 32 words at a time) */
214  if (algo_buffer_size > 0x80)
215  algo_buffer_size &= ~0x7f;
216 
217  /* Write flash helper algorithm into target memory */
218  retval = target_write_buffer(target, algo_base_address,
219  sizeof(cc3220sf_algo), cc3220sf_algo);
220  if (retval != ERROR_OK) {
221  target_free_working_area(target, algo_working_area);
222  target_free_working_area(target, buffer_working_area);
223  return retval;
224  }
225 
226  /* Initialize the ARMv7m specific info to run the algorithm */
229 
230  /* Initialize register params for flash helper algorithm */
231  init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
232  init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
233  init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
234 
235  /* Prepare to write to flash */
236  address = FLASH_BASE_ADDR + offset;
237  remaining = count;
238 
239  /* The flash hardware can only write complete words to flash. If
240  * an unaligned address is passed in, we must do a read-modify-write
241  * on a word with enough bytes to align the rest of the buffer. And
242  * if less than a whole word remains at the end, we must also do a
243  * read-modify-write on a final word to finish up.
244  */
245 
246  /* Do one word write to align address on 32-bit boundary if needed */
247  if (0 != (address & 0x3)) {
248  uint8_t head[4];
249 
250  /* Get starting offset for data to write (will be 1 to 3) */
251  uint32_t head_offset = address & 0x03;
252 
253  /* Get the aligned address to write this first word to */
254  uint32_t head_address = address & 0xfffffffc;
255 
256  /* Retrieve what is already in flash at the head address */
257  retval = target_read_buffer(target, head_address, sizeof(head), head);
258 
259  if (retval == ERROR_OK) {
260  /* Substitute in the new data to write */
261  while ((remaining > 0) && (head_offset < 4)) {
262  head[head_offset] = *buffer;
263  head_offset++;
264  address++;
265  buffer++;
266  remaining--;
267  }
268  }
269 
270  if (retval == ERROR_OK) {
271  /* Helper parameters are passed in registers R0-R2 */
272  /* Set start of data buffer, address to write to, and word count */
273  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
274  buf_set_u32(reg_params[1].value, 0, 32, head_address);
275  buf_set_u32(reg_params[2].value, 0, 32, 1);
276 
277  /* Write head value into buffer to flash */
278  retval = target_write_buffer(target, algo_buffer_address,
279  sizeof(head), head);
280  }
281 
282  if (retval == ERROR_OK) {
283  /* Execute the flash helper algorithm */
284  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
285  algo_base_address, 0, FLASH_TIMEOUT,
287  if (retval != ERROR_OK)
288  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
289 
290  /* Check that the head value was written to flash */
291  result = buf_get_u32(reg_params[2].value, 0, 32);
292  if (result != 0) {
293  retval = ERROR_FAIL;
294  LOG_ERROR("cc3220sf: Flash operation failed");
295  }
296  }
297  }
298 
299  /* Check if there's data at end of buffer that isn't a full word */
300  uint32_t tail_count = remaining & 0x03;
301  /* Adjust remaining so it is a multiple of whole words */
302  remaining -= tail_count;
303 
304  while ((retval == ERROR_OK) && (remaining > 0)) {
305  /* Set start of data buffer and address to write to */
306  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
307  buf_set_u32(reg_params[1].value, 0, 32, address);
308 
309  /* Download data to write into memory buffer */
310  if (remaining >= algo_buffer_size) {
311  /* Fill up buffer with data to flash */
312  retval = target_write_buffer(target, algo_buffer_address,
313  algo_buffer_size, buffer);
314  if (retval != ERROR_OK)
315  break;
316 
317  /* Count to write is in 32-bit words */
318  words = algo_buffer_size / 4;
319 
320  /* Bump variables to next data */
321  address += algo_buffer_size;
322  buffer += algo_buffer_size;
323  remaining -= algo_buffer_size;
324  } else {
325  /* Fill buffer with what's left of the data */
326  retval = target_write_buffer(target, algo_buffer_address,
327  remaining, buffer);
328  if (retval != ERROR_OK)
329  break;
330 
331  /* Calculate the final word count to write */
332  words = remaining / 4;
333  if (0 != (remaining % 4))
334  words++;
335 
336  /* Bump variables to any final data */
337  address += remaining;
338  buffer += remaining;
339  remaining = 0;
340  }
341 
342  /* Set number of words to write */
343  buf_set_u32(reg_params[2].value, 0, 32, words);
344 
345  /* Execute the flash helper algorithm */
346  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
347  algo_base_address, 0, FLASH_TIMEOUT,
349  if (retval != ERROR_OK) {
350  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
351  break;
352  }
353 
354  /* Check that all words were written to flash */
355  result = buf_get_u32(reg_params[2].value, 0, 32);
356  if (result != 0) {
357  retval = ERROR_FAIL;
358  LOG_ERROR("cc3220sf: Flash operation failed");
359  break;
360  }
361 
362  keep_alive();
363  }
364 
365  /* Do one word write for any final bytes less than a full word */
366  if ((retval == ERROR_OK) && (tail_count != 0)) {
367  uint8_t tail[4];
368 
369  /* Set starting byte offset for data to write */
370  uint32_t tail_offset = 0;
371 
372  /* Retrieve what is already in flash at the tail address */
373  retval = target_read_buffer(target, address, sizeof(tail), tail);
374 
375  if (retval == ERROR_OK) {
376  /* Substitute in the new data to write */
377  while (tail_count > 0) {
378  tail[tail_offset] = *buffer;
379  tail_offset++;
380  buffer++;
381  tail_count--;
382  }
383  }
384 
385  if (retval == ERROR_OK) {
386  /* Set start of data buffer, address to write to, and word count */
387  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
388  buf_set_u32(reg_params[1].value, 0, 32, address);
389  buf_set_u32(reg_params[2].value, 0, 32, 1);
390 
391  /* Write tail value into buffer to flash */
392  retval = target_write_buffer(target, algo_buffer_address,
393  sizeof(tail), tail);
394  }
395 
396  if (retval == ERROR_OK) {
397  /* Execute the flash helper algorithm */
398  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
399  algo_base_address, 0, FLASH_TIMEOUT,
401  if (retval != ERROR_OK)
402  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
403 
404  /* Check that the tail was written to flash */
405  result = buf_get_u32(reg_params[2].value, 0, 32);
406  if (result != 0) {
407  retval = ERROR_FAIL;
408  LOG_ERROR("cc3220sf: Flash operation failed");
409  }
410  }
411  }
412 
413  /* Free resources */
414  destroy_reg_param(&reg_params[0]);
415  destroy_reg_param(&reg_params[1]);
416  destroy_reg_param(&reg_params[2]);
417  target_free_working_area(target, algo_working_area);
418  target_free_working_area(target, buffer_working_area);
419 
420  return retval;
421 }
422 
423 static int cc3220sf_probe(struct flash_bank *bank)
424 {
425  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
426 
427  uint32_t base;
428  uint32_t size;
429  unsigned int num_sectors;
430 
431  base = FLASH_BASE_ADDR;
433  num_sectors = FLASH_NUM_SECTORS;
434 
435  free(bank->sectors);
436 
437  bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
438  if (!bank->sectors)
439  return ERROR_FAIL;
440 
441  bank->base = base;
442  bank->size = size;
443  bank->write_start_alignment = 0;
444  bank->write_end_alignment = 0;
445  bank->num_sectors = num_sectors;
446 
447  for (unsigned int i = 0; i < num_sectors; i++) {
448  bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
449  bank->sectors[i].size = FLASH_SECTOR_SIZE;
450  bank->sectors[i].is_erased = -1;
451  bank->sectors[i].is_protected = 0;
452  }
453 
454  /* We've successfully recorded the stats on this flash bank */
455  cc3220sf_bank->probed = true;
456 
457  /* If we fall through to here, then all went well */
458 
459  return ERROR_OK;
460 }
461 
463 {
464  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
465 
466  int retval = ERROR_OK;
467 
468  if (!cc3220sf_bank->probed)
469  retval = cc3220sf_probe(bank);
470 
471  return retval;
472 }
473 
474 static int cc3220sf_info(struct flash_bank *bank, struct command_invocation *cmd)
475 {
476  command_print_sameline(cmd, "CC3220SF with 1MB internal flash\n");
477  return ERROR_OK;
478 }
479 
480 const struct flash_driver cc3220sf_flash = {
481  .name = "cc3220sf",
482  .flash_bank_command = cc3220sf_flash_bank_command,
483  .erase = cc3220sf_erase,
484  .write = cc3220sf_write,
485  .read = default_flash_read,
486  .probe = cc3220sf_probe,
487  .auto_probe = cc3220sf_auto_probe,
488  .erase_check = default_flash_blank_check,
489  .info = cc3220sf_info,
490  .free_driver_priv = default_flash_free_driver_priv,
491 };
#define FLASH_SECTOR_SIZE
Definition: aducm360.c:72
void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction)
Definition: algorithm.c:29
void destroy_reg_param(struct reg_param *param)
Definition: algorithm.c:37
@ PARAM_OUT
Definition: algorithm.h:16
@ PARAM_IN_OUT
Definition: algorithm.h:17
@ ARM_MODE_THREAD
Definition: arm.h:93
#define ARMV7M_COMMON_MAGIC
Definition: armv7m.h:220
Support functions to access arbitrary bits in a byte array.
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned first, unsigned num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:99
static void buf_set_u32(uint8_t *_buffer, unsigned first, unsigned num, uint32_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
Definition: binarybuffer.h:31
static const uint8_t cc3220sf_algo[]
Definition: cc3220sf.c:26
static int cc3220sf_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: cc3220sf.c:103
const struct flash_driver cc3220sf_flash
Definition: cc3220sf.c:480
static int cc3220sf_auto_probe(struct flash_bank *bank)
Definition: cc3220sf.c:462
static int cc3220sf_probe(struct flash_bank *bank)
Definition: cc3220sf.c:423
static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: cc3220sf.c:171
#define FLASH_TIMEOUT
Definition: cc3220sf.c:18
static int cc3220sf_mass_erase(struct flash_bank *bank)
Definition: cc3220sf.c:30
static int cc3220sf_info(struct flash_bank *bank, struct command_invocation *cmd)
Definition: cc3220sf.c:474
FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
Definition: cc3220sf.c:83
#define FLASH_BASE_ADDR
Definition: cc3220sf.h:16
#define FMC_ERASE_BIT
Definition: cc3220sf.h:24
#define FMC_MERASE_BIT
Definition: cc3220sf.h:25
#define FLASH_NUM_SECTORS
Definition: cc3220sf.h:18
#define FMC_MERASE_VALUE
Definition: cc3220sf.h:27
#define FMC_REGISTER_ADDR
Definition: cc3220sf.h:22
#define FMC_ERASE_VALUE
Definition: cc3220sf.h:26
#define FMA_REGISTER_ADDR
Definition: cc3220sf.h:21
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:420
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
uint8_t bank
Definition: esirisc.c:135
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
void keep_alive(void)
Definition: log.c:415
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
unsigned int common_magic
Definition: armv7m.h:295
enum arm_mode core_mode
Definition: armv7m.h:297
bool probed
Definition: cc3220sf.c:21
struct armv7m_algorithm armv7m_info
Definition: cc3220sf.c:22
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
Definition: nor/driver.h:39
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Definition: nor/driver.h:44
Describes the geometry and status of a single flash sector within a flash bank.
Definition: nor/core.h:28
uint8_t * value
Definition: algorithm.h:30
Definition: target.h:116
enum target_state state
Definition: target.h:157
uint32_t size
Definition: target.h:87
target_addr_t address
Definition: target.h:86
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2342
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, target_addr_t entry_point, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
Downloads a target-specific native code algorithm to the target, and executes it.
Definition: target.c:773
uint32_t target_get_working_area_avail(struct target *target)
Definition: target.c:2164
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
Definition: target.c:2060
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2641
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
Definition: target.c:2118
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:790
@ TARGET_HALTED
Definition: target.h:56
int64_t timeval_ms(void)
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22