OpenOCD
ocl.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2007 by Pavel Chromy *
5  * chromy@asix.cz *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include "imp.h"
13 #include "ocl.h"
14 #include <target/embeddedice.h>
15 
16 struct ocl_priv {
18  unsigned int buflen;
19  unsigned int bufalign;
20 };
21 
22 /* flash_bank ocl 0 0 0 0 <target#> */
23 FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
24 {
25  struct arm7_9_common *arm7_9;
26  struct ocl_priv *ocl;
27 
28  if (CMD_ARGC < 6)
30 
31  arm7_9 = target_to_arm7_9(bank->target);
32  if (!is_arm7_9(arm7_9))
33  return ERROR_TARGET_INVALID;
34 
35  ocl = bank->driver_priv = malloc(sizeof(struct ocl_priv));
36  ocl->jtag_info = &arm7_9->jtag_info;
37  ocl->buflen = 0;
38  ocl->bufalign = 1;
39 
40  return ERROR_OK;
41 }
42 
43 static int ocl_erase(struct flash_bank *bank, unsigned int first,
44  unsigned int last)
45 {
46  struct ocl_priv *ocl = bank->driver_priv;
47  int retval;
48  uint32_t dcc_buffer[3];
49 
50  /* check preconditions */
51  if (bank->num_sectors == 0)
53 
54  if (bank->target->state != TARGET_RUNNING) {
55  LOG_ERROR("target has to be running to communicate with the loader");
57  }
58 
59  if ((first == 0) && (last == bank->num_sectors - 1)) {
61  retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
62  if (retval != ERROR_OK)
63  return retval;
64  } else {
66  dcc_buffer[1] = first;
67  dcc_buffer[2] = last;
68  retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
69  if (retval != ERROR_OK)
70  return retval;
71  }
72 
73  /* wait for response, fixed timeout of 1 s */
75  if (retval != ERROR_OK)
76  return retval;
77 
78  /* receive response */
79  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
80  if (retval != ERROR_OK)
81  return retval;
82 
83  if (dcc_buffer[1] != OCL_CMD_DONE) {
84  if (dcc_buffer[0] == OCL_ERASE_ALL)
85  LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
86  else
87  LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
89  }
90 
91  return ERROR_OK;
92 }
93 
94 static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
95 {
96  struct ocl_priv *ocl = bank->driver_priv;
97  int retval;
98  uint32_t *dcc_buffer;
99  uint32_t *dcc_bufptr;
100  int byteofs;
101  int runlen;
102  uint32_t chksum;
103 
104  int i;
105 
106  /* check preconditions */
107  if (ocl->buflen == 0 || ocl->bufalign == 0)
109 
110  if (bank->target->state != TARGET_RUNNING) {
111  LOG_ERROR("target has to be running to communicate with the loader");
113  }
114 
115  /* allocate buffer for max. ocl buffer + overhead */
116  dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
117 
118  while (count) {
119  if (count + (offset % ocl->bufalign) > ocl->buflen)
120  runlen = ocl->buflen - (offset % ocl->bufalign);
121  else
122  runlen = count;
123 
124  dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
125  dcc_buffer[1] = offset;
126  dcc_bufptr = &dcc_buffer[2];
127 
128  *dcc_bufptr = 0xffffffff;
129  byteofs = (offset % ocl->bufalign) % 4;
130  chksum = OCL_CHKS_INIT;
131 
132  /* copy data to DCC buffer in proper byte order and properly aligned */
133  for (i = 0; i < runlen; i++) {
134  switch (byteofs++) {
135  case 0:
136  *dcc_bufptr &= *(buffer++) | 0xffffff00;
137  break;
138  case 1:
139  *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
140  break;
141  case 2:
142  *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
143  break;
144  case 3:
145  *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
146  chksum ^= *(dcc_bufptr++);
147  *dcc_bufptr = 0xffffffff;
148  byteofs = 0;
149  break;
150  }
151  }
152 
153  /* add the remaining word to checksum */
154  if (byteofs)
155  chksum ^= *(dcc_bufptr++);
156 
157  *(dcc_bufptr++) = chksum;
158 
159  /* send the data */
160  retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
161  if (retval != ERROR_OK) {
162  free(dcc_buffer);
163  return retval;
164  }
165 
166  /* wait for response, fixed timeout of 1 s */
168  if (retval != ERROR_OK) {
169  free(dcc_buffer);
170  return retval;
171  }
172 
173  /* receive response */
174  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
175  if (retval != ERROR_OK) {
176  free(dcc_buffer);
177  return retval;
178  }
179 
180  if (dcc_buffer[0] != OCL_CMD_DONE) {
181  LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
182  free(dcc_buffer);
184  }
185 
186  count -= runlen;
187  offset += runlen;
188  }
189 
190  free(dcc_buffer);
191  return ERROR_OK;
192 }
193 
194 static int ocl_probe(struct flash_bank *bank)
195 {
196  struct ocl_priv *ocl = bank->driver_priv;
197  int retval;
198  uint32_t dcc_buffer[1];
199  int sectsize;
200 
201  /* purge pending data in DCC */
203 
204  dcc_buffer[0] = OCL_PROBE;
205  retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
206  if (retval != ERROR_OK)
207  return retval;
208 
209  /* wait for response, fixed timeout of 1 s */
211  if (retval != ERROR_OK)
212  return retval;
213 
214  /* receive response */
215  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
216  if (retval != ERROR_OK)
217  return retval;
218 
219  if (dcc_buffer[0] != OCL_CMD_DONE) {
220  LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
222  }
223 
224  /* receive and fill in parameters, detection of loader is important, receive it one by one */
226  if (retval != ERROR_OK)
227  return retval;
228  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
229  if (retval != ERROR_OK)
230  return retval;
231  bank->base = dcc_buffer[0];
232 
234  if (retval != ERROR_OK)
235  return retval;
236  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
237  if (retval != ERROR_OK)
238  return retval;
239  bank->size = dcc_buffer[0];
240 
242  if (retval != ERROR_OK)
243  return retval;
244  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
245  if (retval != ERROR_OK)
246  return retval;
247  bank->num_sectors = dcc_buffer[0];
248 
250  if (retval != ERROR_OK)
251  return retval;
252  retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
253  if (retval != ERROR_OK)
254  return retval;
255  ocl->buflen = dcc_buffer[0] & 0xffff;
256  ocl->bufalign = dcc_buffer[0] >> 16;
257 
258  bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
259  if (bank->num_sectors == 0) {
260  LOG_ERROR("number of sectors shall be non zero value");
262  }
263  if (bank->size % bank->num_sectors) {
264  LOG_ERROR("bank size not divisible by number of sectors");
266  }
267  sectsize = bank->size / bank->num_sectors;
268  for (unsigned int i = 0; i < bank->num_sectors; i++) {
269  bank->sectors[i].offset = i * sectsize;
270  bank->sectors[i].size = sectsize;
271  bank->sectors[i].is_erased = -1;
272  bank->sectors[i].is_protected = -1;
273  }
274 
275  if (ocl->bufalign == 0)
276  ocl->bufalign = 1;
277 
278  if (ocl->buflen == 0) {
279  LOG_ERROR("buflen shall be non zero value");
281  }
282 
283  if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
284  LOG_ERROR("buflen is not multiple of bufalign");
286  }
287 
288  if (ocl->buflen % 4) {
289  LOG_ERROR("buflen shall be divisible by 4");
291  }
292 
293  return ERROR_OK;
294 }
295 
296 static int ocl_auto_probe(struct flash_bank *bank)
297 {
298  struct ocl_priv *ocl = bank->driver_priv;
299 
300  if (ocl->buflen == 0 || ocl->bufalign == 0)
302 
303  return ERROR_OK;
304 }
305 
306 const struct flash_driver ocl_flash = {
307  .name = "ocl",
308  .flash_bank_command = ocl_flash_bank_command,
309  .erase = ocl_erase,
310  .write = ocl_write,
311  .read = default_flash_read,
312  .probe = ocl_probe,
313  .erase_check = default_flash_blank_check,
314  .auto_probe = ocl_auto_probe,
315  .free_driver_priv = default_flash_free_driver_priv,
316 };
static const uint8_t * dcc_buffer
static struct arm7_9_common * target_to_arm7_9(struct target *target)
static bool is_arm7_9(struct arm7_9_common *arm7_9)
#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
int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout)
Poll DCC control register until read or write handshake completes.
Definition: embeddedice.c:577
int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
Send a block of size 32-bit words to the DCC.
Definition: embeddedice.c:532
int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
Receive a block of size 32-bit words from the DCC.
Definition: embeddedice.c:412
@ EICE_COMM_CTRL_WBIT
Definition: embeddedice.h:69
uint8_t bank
Definition: esirisc.c:135
#define ERROR_FLASH_BANK_INVALID
Definition: flash/common.h:28
#define ERROR_FLASH_BANK_NOT_PROBED
Definition: flash/common.h:35
#define ERROR_FLASH_OPERATION_FAILED
Definition: flash/common.h:30
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.
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
Definition: ocl.c:23
static int ocl_probe(struct flash_bank *bank)
Definition: ocl.c:194
static int ocl_auto_probe(struct flash_bank *bank)
Definition: ocl.c:296
static int ocl_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: ocl.c:43
static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: ocl.c:94
const struct flash_driver ocl_flash
Definition: ocl.c:306
#define OCL_CHKS_INIT
Definition: ocl.h:26
#define OCL_CMD_DONE
Definition: ocl.h:21
#define OCL_ERASE_ALL
Definition: ocl.h:17
#define OCL_PROBE
Definition: ocl.h:18
#define OCL_ERASE_BLOCK
Definition: ocl.h:16
#define OCL_FLASH_BLOCK
Definition: ocl.h:15
Structure for items that are common between both ARM7 and ARM9 targets.
Definition: arm7_9_common.h:28
struct arm_jtag jtag_info
JTAG information for target.
Definition: arm7_9_common.h:33
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
Definition: ocl.c:16
unsigned int buflen
Definition: ocl.c:18
struct arm_jtag * jtag_info
Definition: ocl.c:17
unsigned int bufalign
Definition: ocl.c:19
#define ERROR_TARGET_INVALID
Definition: target.h:787
@ TARGET_RUNNING
Definition: target.h:55
#define ERROR_TARGET_NOT_RUNNING
Definition: target.h:796
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22