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  bank->next = NULL;
100 
101  return ERROR_OK;
102 }
103 
104 static int cc3220sf_erase(struct flash_bank *bank, unsigned int first,
105  unsigned int last)
106 {
107  struct target *target = bank->target;
108  bool done;
109  long long start_ms;
110  long long elapsed_ms;
111  uint32_t address;
112  uint32_t value;
113 
114  int retval = ERROR_OK;
115 
116  if (target->state != TARGET_HALTED) {
117  LOG_ERROR("Target not halted");
119  }
120 
121  /* Do a mass erase if user requested all sectors of flash */
122  if ((first == 0) && (last == (bank->num_sectors - 1))) {
123  /* Request mass erase of flash */
124  return cc3220sf_mass_erase(bank);
125  }
126 
127  /* Erase requested sectors one by one */
128  for (unsigned int i = first; i <= last; i++) {
129 
130  /* Determine address of sector to erase */
131  address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE;
132 
133  /* Set starting address to erase */
134  retval = target_write_u32(target, FMA_REGISTER_ADDR, address);
135  if (retval != ERROR_OK)
136  return retval;
137 
138  /* Write the ERASE bit of the FMC register */
140  if (retval != ERROR_OK)
141  return retval;
142 
143  /* Poll the ERASE bit until the erase is complete */
144  done = false;
145  start_ms = timeval_ms();
146  while (!done) {
147  retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
148  if (retval != ERROR_OK)
149  return retval;
150 
151  if ((value & FMC_ERASE_BIT) == 0) {
152  /* Bit clears when mass erase is finished */
153  done = true;
154  } else {
155  elapsed_ms = timeval_ms() - start_ms;
156  if (elapsed_ms > 500)
157  keep_alive();
158  if (elapsed_ms > FLASH_TIMEOUT)
159  break;
160  }
161  }
162 
163  if (!done) {
164  /* Sector erase timed out waiting for confirmation */
165  return ERROR_FAIL;
166  }
167  }
168 
169  return retval;
170 }
171 
172 static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
173  uint32_t offset, uint32_t count)
174 {
175  struct target *target = bank->target;
176  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
177  struct working_area *algo_working_area;
178  struct working_area *buffer_working_area;
179  struct reg_param reg_params[3];
180  uint32_t algo_base_address;
181  uint32_t algo_buffer_address;
182  uint32_t algo_buffer_size;
183  uint32_t address;
184  uint32_t remaining;
185  uint32_t words;
186  uint32_t result;
187 
188  int retval = ERROR_OK;
189 
190  if (target->state != TARGET_HALTED) {
191  LOG_ERROR("Target not halted");
193  }
194 
195  /* Obtain working area to use for flash helper algorithm */
197  &algo_working_area);
198  if (retval != ERROR_OK)
199  return retval;
200 
201  /* Obtain working area to use for flash buffer */
203  target_get_working_area_avail(target), &buffer_working_area);
204  if (retval != ERROR_OK) {
205  target_free_working_area(target, algo_working_area);
206  return retval;
207  }
208 
209  algo_base_address = algo_working_area->address;
210  algo_buffer_address = buffer_working_area->address;
211  algo_buffer_size = buffer_working_area->size;
212 
213  /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
214  /* (algo runs more efficiently if it operates on 32 words at a time) */
215  if (algo_buffer_size > 0x80)
216  algo_buffer_size &= ~0x7f;
217 
218  /* Write flash helper algorithm into target memory */
219  retval = target_write_buffer(target, algo_base_address,
220  sizeof(cc3220sf_algo), cc3220sf_algo);
221  if (retval != ERROR_OK) {
222  target_free_working_area(target, algo_working_area);
223  target_free_working_area(target, buffer_working_area);
224  return retval;
225  }
226 
227  /* Initialize the ARMv7m specific info to run the algorithm */
230 
231  /* Initialize register params for flash helper algorithm */
232  init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
233  init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
234  init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
235 
236  /* Prepare to write to flash */
237  address = FLASH_BASE_ADDR + offset;
238  remaining = count;
239 
240  /* The flash hardware can only write complete words to flash. If
241  * an unaligned address is passed in, we must do a read-modify-write
242  * on a word with enough bytes to align the rest of the buffer. And
243  * if less than a whole word remains at the end, we must also do a
244  * read-modify-write on a final word to finish up.
245  */
246 
247  /* Do one word write to align address on 32-bit boundary if needed */
248  if (0 != (address & 0x3)) {
249  uint8_t head[4];
250 
251  /* Get starting offset for data to write (will be 1 to 3) */
252  uint32_t head_offset = address & 0x03;
253 
254  /* Get the aligned address to write this first word to */
255  uint32_t head_address = address & 0xfffffffc;
256 
257  /* Retrieve what is already in flash at the head address */
258  retval = target_read_buffer(target, head_address, sizeof(head), head);
259 
260  if (retval == ERROR_OK) {
261  /* Substitute in the new data to write */
262  while ((remaining > 0) && (head_offset < 4)) {
263  head[head_offset] = *buffer;
264  head_offset++;
265  address++;
266  buffer++;
267  remaining--;
268  }
269  }
270 
271  if (retval == ERROR_OK) {
272  /* Helper parameters are passed in registers R0-R2 */
273  /* Set start of data buffer, address to write to, and word count */
274  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
275  buf_set_u32(reg_params[1].value, 0, 32, head_address);
276  buf_set_u32(reg_params[2].value, 0, 32, 1);
277 
278  /* Write head value into buffer to flash */
279  retval = target_write_buffer(target, algo_buffer_address,
280  sizeof(head), head);
281  }
282 
283  if (retval == ERROR_OK) {
284  /* Execute the flash helper algorithm */
285  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
286  algo_base_address, 0, FLASH_TIMEOUT,
288  if (retval != ERROR_OK)
289  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
290 
291  /* Check that the head value was written to flash */
292  result = buf_get_u32(reg_params[2].value, 0, 32);
293  if (result != 0) {
294  retval = ERROR_FAIL;
295  LOG_ERROR("cc3220sf: Flash operation failed");
296  }
297  }
298  }
299 
300  /* Check if there's data at end of buffer that isn't a full word */
301  uint32_t tail_count = remaining & 0x03;
302  /* Adjust remaining so it is a multiple of whole words */
303  remaining -= tail_count;
304 
305  while ((retval == ERROR_OK) && (remaining > 0)) {
306  /* Set start of data buffer and address to write to */
307  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
308  buf_set_u32(reg_params[1].value, 0, 32, address);
309 
310  /* Download data to write into memory buffer */
311  if (remaining >= algo_buffer_size) {
312  /* Fill up buffer with data to flash */
313  retval = target_write_buffer(target, algo_buffer_address,
314  algo_buffer_size, buffer);
315  if (retval != ERROR_OK)
316  break;
317 
318  /* Count to write is in 32-bit words */
319  words = algo_buffer_size / 4;
320 
321  /* Bump variables to next data */
322  address += algo_buffer_size;
323  buffer += algo_buffer_size;
324  remaining -= algo_buffer_size;
325  } else {
326  /* Fill buffer with what's left of the data */
327  retval = target_write_buffer(target, algo_buffer_address,
328  remaining, buffer);
329  if (retval != ERROR_OK)
330  break;
331 
332  /* Calculate the final word count to write */
333  words = remaining / 4;
334  if (0 != (remaining % 4))
335  words++;
336 
337  /* Bump variables to any final data */
338  address += remaining;
339  buffer += remaining;
340  remaining = 0;
341  }
342 
343  /* Set number of words to write */
344  buf_set_u32(reg_params[2].value, 0, 32, words);
345 
346  /* Execute the flash helper algorithm */
347  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
348  algo_base_address, 0, FLASH_TIMEOUT,
350  if (retval != ERROR_OK) {
351  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
352  break;
353  }
354 
355  /* Check that all words were written to flash */
356  result = buf_get_u32(reg_params[2].value, 0, 32);
357  if (result != 0) {
358  retval = ERROR_FAIL;
359  LOG_ERROR("cc3220sf: Flash operation failed");
360  break;
361  }
362 
363  keep_alive();
364  }
365 
366  /* Do one word write for any final bytes less than a full word */
367  if ((retval == ERROR_OK) && (tail_count != 0)) {
368  uint8_t tail[4];
369 
370  /* Set starting byte offset for data to write */
371  uint32_t tail_offset = 0;
372 
373  /* Retrieve what is already in flash at the tail address */
374  retval = target_read_buffer(target, address, sizeof(tail), tail);
375 
376  if (retval == ERROR_OK) {
377  /* Substitute in the new data to write */
378  while (tail_count > 0) {
379  tail[tail_offset] = *buffer;
380  tail_offset++;
381  buffer++;
382  tail_count--;
383  }
384  }
385 
386  if (retval == ERROR_OK) {
387  /* Set start of data buffer, address to write to, and word count */
388  buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
389  buf_set_u32(reg_params[1].value, 0, 32, address);
390  buf_set_u32(reg_params[2].value, 0, 32, 1);
391 
392  /* Write tail value into buffer to flash */
393  retval = target_write_buffer(target, algo_buffer_address,
394  sizeof(tail), tail);
395  }
396 
397  if (retval == ERROR_OK) {
398  /* Execute the flash helper algorithm */
399  retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
400  algo_base_address, 0, FLASH_TIMEOUT,
402  if (retval != ERROR_OK)
403  LOG_ERROR("cc3220sf: Flash algorithm failed to run");
404 
405  /* Check that the tail was written to flash */
406  result = buf_get_u32(reg_params[2].value, 0, 32);
407  if (result != 0) {
408  retval = ERROR_FAIL;
409  LOG_ERROR("cc3220sf: Flash operation failed");
410  }
411  }
412  }
413 
414  /* Free resources */
415  destroy_reg_param(&reg_params[0]);
416  destroy_reg_param(&reg_params[1]);
417  destroy_reg_param(&reg_params[2]);
418  target_free_working_area(target, algo_working_area);
419  target_free_working_area(target, buffer_working_area);
420 
421  return retval;
422 }
423 
424 static int cc3220sf_probe(struct flash_bank *bank)
425 {
426  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
427 
428  uint32_t base;
429  uint32_t size;
430  unsigned int num_sectors;
431 
432  base = FLASH_BASE_ADDR;
434  num_sectors = FLASH_NUM_SECTORS;
435 
436  free(bank->sectors);
437 
438  bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
439  if (!bank->sectors)
440  return ERROR_FAIL;
441 
442  bank->base = base;
443  bank->size = size;
444  bank->write_start_alignment = 0;
445  bank->write_end_alignment = 0;
446  bank->num_sectors = num_sectors;
447 
448  for (unsigned int i = 0; i < num_sectors; i++) {
449  bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
450  bank->sectors[i].size = FLASH_SECTOR_SIZE;
451  bank->sectors[i].is_erased = -1;
452  bank->sectors[i].is_protected = 0;
453  }
454 
455  /* We've successfully recorded the stats on this flash bank */
456  cc3220sf_bank->probed = true;
457 
458  /* If we fall through to here, then all went well */
459 
460  return ERROR_OK;
461 }
462 
464 {
465  struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
466 
467  int retval = ERROR_OK;
468 
469  if (!cc3220sf_bank->probed)
470  retval = cc3220sf_probe(bank);
471 
472  return retval;
473 }
474 
475 static int cc3220sf_info(struct flash_bank *bank, struct command_invocation *cmd)
476 {
477  command_print_sameline(cmd, "CC3220SF with 1MB internal flash\n");
478  return ERROR_OK;
479 }
480 
481 const struct flash_driver cc3220sf_flash = {
482  .name = "cc3220sf",
483  .flash_bank_command = cc3220sf_flash_bank_command,
484  .erase = cc3220sf_erase,
485  .write = cc3220sf_write,
486  .read = default_flash_read,
487  .probe = cc3220sf_probe,
488  .auto_probe = cc3220sf_auto_probe,
489  .erase_check = default_flash_blank_check,
490  .info = cc3220sf_info,
491  .free_driver_priv = default_flash_free_driver_priv,
492 };
#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:86
#define ARMV7M_COMMON_MAGIC
Definition: armv7m.h:218
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:98
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:30
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:104
const struct flash_driver cc3220sf_flash
Definition: cc3220sf.c:481
static int cc3220sf_auto_probe(struct flash_bank *bank)
Definition: cc3220sf.c:463
static int cc3220sf_probe(struct flash_bank *bank)
Definition: cc3220sf.c:424
static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: cc3220sf.c:172
#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:475
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:450
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:385
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:150
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:419
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define ERROR_OK
Definition: log.h:155
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
unsigned int common_magic
Definition: armv7m.h:293
enum arm_mode core_mode
Definition: armv7m.h:295
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:120
enum target_state state
Definition: target.h:162
uint32_t size
Definition: target.h:91
target_addr_t address
Definition: target.h:90
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2408
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2473
uint32_t target_get_working_area_avail(struct target *target)
Definition: target.c:2233
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
Definition: target.c:2129
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2707
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
Definition: target.c:2187
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, int timeout_ms, void *arch_info)
Downloads a target-specific native code algorithm to the target, and executes it.
Definition: target.c:846
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2616
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:792
@ TARGET_HALTED
Definition: target.h:55
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