stm32x.c 32.6 KB
Newer Older
oharboe's avatar
oharboe committed
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
6
7
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
oharboe's avatar
oharboe committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "stm32x.h"
#include "armv7m.h"
#include "binarybuffer.h"


mifi's avatar
mifi committed
32
33
34
35
static int stm32x_register_commands(struct command_context_s *cmd_ctx);
static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
static int stm32x_erase(struct flash_bank_s *bank, int first, int last);
static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last);
36
static int stm32x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
mifi's avatar
mifi committed
37
38
39
40
41
static int stm32x_probe(struct flash_bank_s *bank);
static int stm32x_auto_probe(struct flash_bank_s *bank);
//static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_protect_check(struct flash_bank_s *bank);
static int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size);
oharboe's avatar
oharboe committed
42

mifi's avatar
mifi committed
43
44
45
46
47
48
static int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stm32x_mass_erase(struct flash_bank_s *bank);
oharboe's avatar
oharboe committed
49
50
51
52
53
54
55
56
57
58
59

flash_driver_t stm32x_flash =
{
	.name = "stm32x",
	.register_commands = stm32x_register_commands,
	.flash_bank_command = stm32x_flash_bank_command,
	.erase = stm32x_erase,
	.protect = stm32x_protect,
	.write = stm32x_write,
	.probe = stm32x_probe,
	.auto_probe = stm32x_auto_probe,
60
	.erase_check = default_flash_mem_blank_check,
oharboe's avatar
oharboe committed
61
62
63
64
	.protect_check = stm32x_protect_check,
	.info = stm32x_info
};

mifi's avatar
mifi committed
65
static int stm32x_register_commands(struct command_context_s *cmd_ctx)
oharboe's avatar
oharboe committed
66
67
{
	command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stm32x", NULL, COMMAND_ANY, "stm32x flash specific commands");
zwelch's avatar
zwelch committed
68

oharboe's avatar
oharboe committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	register_command(cmd_ctx, stm32x_cmd, "lock", stm32x_handle_lock_command, COMMAND_EXEC,
					 "lock device");
	register_command(cmd_ctx, stm32x_cmd, "unlock", stm32x_handle_unlock_command, COMMAND_EXEC,
					 "unlock protected device");
	register_command(cmd_ctx, stm32x_cmd, "mass_erase", stm32x_handle_mass_erase_command, COMMAND_EXEC,
					 "mass erase device");
	register_command(cmd_ctx, stm32x_cmd, "options_read", stm32x_handle_options_read_command, COMMAND_EXEC,
					 "read device option bytes");
	register_command(cmd_ctx, stm32x_cmd, "options_write", stm32x_handle_options_write_command, COMMAND_EXEC,
					 "write device option bytes");
	return ERROR_OK;
}

/* flash bank stm32x <base> <size> 0 0 <target#>
 */
mifi's avatar
mifi committed
84
static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
85
86
{
	stm32x_flash_bank_t *stm32x_info;
zwelch's avatar
zwelch committed
87

oharboe's avatar
oharboe committed
88
89
	if (argc < 6)
	{
90
		LOG_WARNING("incomplete flash_bank stm32x configuration");
oharboe's avatar
oharboe committed
91
92
		return ERROR_FLASH_BANK_INVALID;
	}
zwelch's avatar
zwelch committed
93

oharboe's avatar
oharboe committed
94
95
	stm32x_info = malloc(sizeof(stm32x_flash_bank_t));
	bank->driver_priv = stm32x_info;
zwelch's avatar
zwelch committed
96

oharboe's avatar
oharboe committed
97
98
	stm32x_info->write_algorithm = NULL;
	stm32x_info->probed = 0;
zwelch's avatar
zwelch committed
99

oharboe's avatar
oharboe committed
100
101
102
	return ERROR_OK;
}

103
static uint32_t stm32x_get_flash_status(flash_bank_t *bank)
oharboe's avatar
oharboe committed
104
105
{
	target_t *target = bank->target;
106
	uint32_t status;
zwelch's avatar
zwelch committed
107

oharboe's avatar
oharboe committed
108
	target_read_u32(target, STM32_FLASH_SR, &status);
zwelch's avatar
zwelch committed
109

oharboe's avatar
oharboe committed
110
111
112
	return status;
}

113
static uint32_t stm32x_wait_status_busy(flash_bank_t *bank, int timeout)
oharboe's avatar
oharboe committed
114
{
115
	target_t *target = bank->target;
116
	uint32_t status;
zwelch's avatar
zwelch committed
117

oharboe's avatar
oharboe committed
118
119
120
	/* wait for busy to clear */
	while (((status = stm32x_get_flash_status(bank)) & FLASH_BSY) && (timeout-- > 0))
	{
duane's avatar
duane committed
121
		LOG_DEBUG("status: 0x%" PRIx32 "", status);
122
		alive_sleep(1);
oharboe's avatar
oharboe committed
123
	}
124
	/* Clear but report errors */
zwelch's avatar
zwelch committed
125
	if (status & (FLASH_WRPRTERR | FLASH_PGERR))
126
	{
zwelch's avatar
zwelch committed
127
		target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR | FLASH_PGERR);
128
	}
oharboe's avatar
oharboe committed
129
130
131
	return status;
}

mifi's avatar
mifi committed
132
static int stm32x_read_options(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
133
{
134
	uint32_t optiondata;
oharboe's avatar
oharboe committed
135
136
	stm32x_flash_bank_t *stm32x_info = NULL;
	target_t *target = bank->target;
zwelch's avatar
zwelch committed
137

oharboe's avatar
oharboe committed
138
	stm32x_info = bank->driver_priv;
zwelch's avatar
zwelch committed
139

oharboe's avatar
oharboe committed
140
141
	/* read current option bytes */
	target_read_u32(target, STM32_FLASH_OBR, &optiondata);
zwelch's avatar
zwelch committed
142

zwelch's avatar
zwelch committed
143
	stm32x_info->option_bytes.user_options = (uint16_t)0xFFF8 | ((optiondata >> 2) & 0x07);
oharboe's avatar
oharboe committed
144
	stm32x_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5;
zwelch's avatar
zwelch committed
145

oharboe's avatar
oharboe committed
146
	if (optiondata & (1 << OPT_READOUT))
147
		LOG_INFO("Device Security Bit Set");
zwelch's avatar
zwelch committed
148

oharboe's avatar
oharboe committed
149
150
	/* each bit refers to a 4bank protection */
	target_read_u32(target, STM32_FLASH_WRPR, &optiondata);
zwelch's avatar
zwelch committed
151

zwelch's avatar
zwelch committed
152
153
154
155
	stm32x_info->option_bytes.protection[0] = (uint16_t)optiondata;
	stm32x_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8);
	stm32x_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16);
	stm32x_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24);
zwelch's avatar
zwelch committed
156

oharboe's avatar
oharboe committed
157
158
159
	return ERROR_OK;
}

mifi's avatar
mifi committed
160
static int stm32x_erase_options(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
161
162
163
{
	stm32x_flash_bank_t *stm32x_info = NULL;
	target_t *target = bank->target;
164
	uint32_t status;
zwelch's avatar
zwelch committed
165

oharboe's avatar
oharboe committed
166
	stm32x_info = bank->driver_priv;
zwelch's avatar
zwelch committed
167

oharboe's avatar
oharboe committed
168
169
	/* read current options */
	stm32x_read_options(bank);
zwelch's avatar
zwelch committed
170

oharboe's avatar
oharboe committed
171
172
173
	/* unlock flash registers */
	target_write_u32(target, STM32_FLASH_KEYR, KEY1);
	target_write_u32(target, STM32_FLASH_KEYR, KEY2);
zwelch's avatar
zwelch committed
174

oharboe's avatar
oharboe committed
175
176
177
	/* unlock option flash registers */
	target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1);
	target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2);
zwelch's avatar
zwelch committed
178

oharboe's avatar
oharboe committed
179
	/* erase option bytes */
zwelch's avatar
zwelch committed
180
181
	target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER | FLASH_OPTWRE);
	target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
zwelch's avatar
zwelch committed
182

oharboe's avatar
oharboe committed
183
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
184

zwelch's avatar
zwelch committed
185
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
186
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
187
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
188
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
189

oharboe's avatar
oharboe committed
190
191
192
	/* clear readout protection and complementary option bytes
	 * this will also force a device unlock if set */
	stm32x_info->option_bytes.RDP = 0x5AA5;
zwelch's avatar
zwelch committed
193

oharboe's avatar
oharboe committed
194
195
196
	return ERROR_OK;
}

mifi's avatar
mifi committed
197
static int stm32x_write_options(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
198
199
200
{
	stm32x_flash_bank_t *stm32x_info = NULL;
	target_t *target = bank->target;
201
	uint32_t status;
zwelch's avatar
zwelch committed
202

oharboe's avatar
oharboe committed
203
	stm32x_info = bank->driver_priv;
zwelch's avatar
zwelch committed
204

oharboe's avatar
oharboe committed
205
206
207
	/* unlock flash registers */
	target_write_u32(target, STM32_FLASH_KEYR, KEY1);
	target_write_u32(target, STM32_FLASH_KEYR, KEY2);
zwelch's avatar
zwelch committed
208

oharboe's avatar
oharboe committed
209
210
211
	/* unlock option flash registers */
	target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1);
	target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2);
zwelch's avatar
zwelch committed
212

oharboe's avatar
oharboe committed
213
	/* program option bytes */
zwelch's avatar
zwelch committed
214
	target_write_u32(target, STM32_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE);
zwelch's avatar
zwelch committed
215

oharboe's avatar
oharboe committed
216
217
	/* write user option byte */
	target_write_u16(target, STM32_OB_USER, stm32x_info->option_bytes.user_options);
zwelch's avatar
zwelch committed
218

oharboe's avatar
oharboe committed
219
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
220

zwelch's avatar
zwelch committed
221
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
222
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
223
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
224
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
225

oharboe's avatar
oharboe committed
226
227
	/* write protection byte 1 */
	target_write_u16(target, STM32_OB_WRP0, stm32x_info->option_bytes.protection[0]);
zwelch's avatar
zwelch committed
228

oharboe's avatar
oharboe committed
229
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
230

zwelch's avatar
zwelch committed
231
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
232
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
233
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
234
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
235

oharboe's avatar
oharboe committed
236
237
	/* write protection byte 2 */
	target_write_u16(target, STM32_OB_WRP1, stm32x_info->option_bytes.protection[1]);
zwelch's avatar
zwelch committed
238

oharboe's avatar
oharboe committed
239
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
240

zwelch's avatar
zwelch committed
241
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
242
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
243
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
244
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
245

oharboe's avatar
oharboe committed
246
247
	/* write protection byte 3 */
	target_write_u16(target, STM32_OB_WRP2, stm32x_info->option_bytes.protection[2]);
zwelch's avatar
zwelch committed
248

oharboe's avatar
oharboe committed
249
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
250

zwelch's avatar
zwelch committed
251
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
252
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
253
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
254
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
255

oharboe's avatar
oharboe committed
256
257
	/* write protection byte 4 */
	target_write_u16(target, STM32_OB_WRP3, stm32x_info->option_bytes.protection[3]);
zwelch's avatar
zwelch committed
258

oharboe's avatar
oharboe committed
259
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
260

zwelch's avatar
zwelch committed
261
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
262
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
263
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
264
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
265

oharboe's avatar
oharboe committed
266
267
	/* write readout protection bit */
	target_write_u16(target, STM32_OB_RDP, stm32x_info->option_bytes.RDP);
zwelch's avatar
zwelch committed
268

oharboe's avatar
oharboe committed
269
	status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
270

zwelch's avatar
zwelch committed
271
	if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
272
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
273
	if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
274
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
275

oharboe's avatar
oharboe committed
276
	target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
zwelch's avatar
zwelch committed
277

oharboe's avatar
oharboe committed
278
279
280
	return ERROR_OK;
}

mifi's avatar
mifi committed
281
static int stm32x_protect_check(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
282
283
{
	target_t *target = bank->target;
284
	stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
zwelch's avatar
zwelch committed
285

286
	uint32_t protection;
oharboe's avatar
oharboe committed
287
288
	int i, s;
	int num_bits;
289
	int set;
zwelch's avatar
zwelch committed
290

oharboe's avatar
oharboe committed
291
292
	if (target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
293
		LOG_ERROR("Target not halted");
oharboe's avatar
oharboe committed
294
295
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
296
297

	/* medium density - each bit refers to a 4bank protection
298
	 * high density - each bit refers to a 2bank protection */
oharboe's avatar
oharboe committed
299
	target_read_u32(target, STM32_FLASH_WRPR, &protection);
zwelch's avatar
zwelch committed
300

301
302
303
	/* medium density - each protection bit is for 4 * 1K pages
	 * high density - each protection bit is for 2 * 2K pages */
	num_bits = (bank->num_sectors / stm32x_info->ppage_size);
zwelch's avatar
zwelch committed
304

305
	if (stm32x_info->ppage_size == 2)
oharboe's avatar
oharboe committed
306
	{
307
		/* high density flash */
zwelch's avatar
zwelch committed
308

309
		set = 1;
zwelch's avatar
zwelch committed
310

311
		if (protection & (1 << 31))
oharboe's avatar
oharboe committed
312
			set = 0;
zwelch's avatar
zwelch committed
313
314

		/* bit 31 controls sector 62 - 255 protection */
315
316
317
318
		for (s = 62; s < bank->num_sectors; s++)
		{
			bank->sectors[s].is_protected = set;
		}
zwelch's avatar
zwelch committed
319

320
321
		if (bank->num_sectors > 61)
			num_bits = 31;
zwelch's avatar
zwelch committed
322

323
324
325
		for (i = 0; i < num_bits; i++)
		{
			set = 1;
zwelch's avatar
zwelch committed
326

327
328
			if (protection & (1 << i))
				set = 0;
zwelch's avatar
zwelch committed
329

330
331
332
			for (s = 0; s < stm32x_info->ppage_size; s++)
				bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
		}
oharboe's avatar
oharboe committed
333
	}
334
	else
zwelch's avatar
zwelch committed
335
	{
336
337
338
339
		/* medium density flash */
		for (i = 0; i < num_bits; i++)
		{
			set = 1;
zwelch's avatar
zwelch committed
340

zwelch's avatar
zwelch committed
341
			if ( protection & (1 << i))
342
				set = 0;
zwelch's avatar
zwelch committed
343

344
345
346
347
			for (s = 0; s < stm32x_info->ppage_size; s++)
				bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
		}
	}
zwelch's avatar
zwelch committed
348

oharboe's avatar
oharboe committed
349
350
351
	return ERROR_OK;
}

mifi's avatar
mifi committed
352
static int stm32x_erase(struct flash_bank_s *bank, int first, int last)
oharboe's avatar
oharboe committed
353
354
355
{
	target_t *target = bank->target;
	int i;
356
	uint32_t status;
zwelch's avatar
zwelch committed
357

358
359
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
360
		LOG_ERROR("Target not halted");
361
362
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
363

364
365
366
367
	if ((first == 0) && (last == (bank->num_sectors - 1)))
	{
		return stm32x_mass_erase(bank);
	}
zwelch's avatar
zwelch committed
368

oharboe's avatar
oharboe committed
369
370
371
	/* unlock flash registers */
	target_write_u32(target, STM32_FLASH_KEYR, KEY1);
	target_write_u32(target, STM32_FLASH_KEYR, KEY2);
zwelch's avatar
zwelch committed
372

oharboe's avatar
oharboe committed
373
	for (i = first; i <= last; i++)
zwelch's avatar
zwelch committed
374
	{
oharboe's avatar
oharboe committed
375
376
		target_write_u32(target, STM32_FLASH_CR, FLASH_PER);
		target_write_u32(target, STM32_FLASH_AR, bank->base + bank->sectors[i].offset);
zwelch's avatar
zwelch committed
377
		target_write_u32(target, STM32_FLASH_CR, FLASH_PER | FLASH_STRT);
zwelch's avatar
zwelch committed
378

oharboe's avatar
oharboe committed
379
		status = stm32x_wait_status_busy(bank, 10);
zwelch's avatar
zwelch committed
380

zwelch's avatar
zwelch committed
381
		if ( status & FLASH_WRPRTERR )
oharboe's avatar
oharboe committed
382
			return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
383
		if ( status & FLASH_PGERR )
oharboe's avatar
oharboe committed
384
385
386
387
388
			return ERROR_FLASH_OPERATION_FAILED;
		bank->sectors[i].is_erased = 1;
	}

	target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
zwelch's avatar
zwelch committed
389

oharboe's avatar
oharboe committed
390
391
392
	return ERROR_OK;
}

mifi's avatar
mifi committed
393
static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last)
oharboe's avatar
oharboe committed
394
395
396
{
	stm32x_flash_bank_t *stm32x_info = NULL;
	target_t *target = bank->target;
zwelch's avatar
zwelch committed
397
	uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
oharboe's avatar
oharboe committed
398
399
	int i, reg, bit;
	int status;
400
	uint32_t protection;
zwelch's avatar
zwelch committed
401

oharboe's avatar
oharboe committed
402
	stm32x_info = bank->driver_priv;
zwelch's avatar
zwelch committed
403

oharboe's avatar
oharboe committed
404
405
	if (target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
406
		LOG_ERROR("Target not halted");
oharboe's avatar
oharboe committed
407
408
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
409

410
	if ((first && (first % stm32x_info->ppage_size)) || ((last + 1) && (last + 1) % stm32x_info->ppage_size))
oharboe's avatar
oharboe committed
411
	{
412
		LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", stm32x_info->ppage_size);
oharboe's avatar
oharboe committed
413
414
		return ERROR_FLASH_SECTOR_INVALID;
	}
zwelch's avatar
zwelch committed
415
416

	/* medium density - each bit refers to a 4bank protection
417
	 * high density - each bit refers to a 2bank protection */
oharboe's avatar
oharboe committed
418
	target_read_u32(target, STM32_FLASH_WRPR, &protection);
zwelch's avatar
zwelch committed
419

zwelch's avatar
zwelch committed
420
421
422
423
	prot_reg[0] = (uint16_t)protection;
	prot_reg[1] = (uint16_t)(protection >> 8);
	prot_reg[2] = (uint16_t)(protection >> 16);
	prot_reg[3] = (uint16_t)(protection >> 24);
zwelch's avatar
zwelch committed
424

425
	if (stm32x_info->ppage_size == 2)
oharboe's avatar
oharboe committed
426
	{
427
		/* high density flash */
zwelch's avatar
zwelch committed
428

429
		/* bit 7 controls sector 62 - 255 protection */
430
431
432
433
434
435
436
		if (last > 61)
		{
			if (set)
				prot_reg[3] &= ~(1 << 7);
			else
				prot_reg[3] |= (1 << 7);
		}
zwelch's avatar
zwelch committed
437

438
		if (first > 61)
439
			first = 62;
440
441
		if (last > 61)
			last = 61;
zwelch's avatar
zwelch committed
442

443
444
445
446
		for (i = first; i <= last; i++)
		{
			reg = (i / stm32x_info->ppage_size) / 8;
			bit = (i / stm32x_info->ppage_size) - (reg * 8);
zwelch's avatar
zwelch committed
447

zwelch's avatar
zwelch committed
448
			if ( set )
449
450
451
452
453
454
455
456
457
458
459
460
				prot_reg[reg] &= ~(1 << bit);
			else
				prot_reg[reg] |= (1 << bit);
		}
	}
	else
	{
		/* medium density flash */
		for (i = first; i <= last; i++)
		{
			reg = (i / stm32x_info->ppage_size) / 8;
			bit = (i / stm32x_info->ppage_size) - (reg * 8);
zwelch's avatar
zwelch committed
461

zwelch's avatar
zwelch committed
462
			if ( set )
463
464
465
466
				prot_reg[reg] &= ~(1 << bit);
			else
				prot_reg[reg] |= (1 << bit);
		}
oharboe's avatar
oharboe committed
467
	}
zwelch's avatar
zwelch committed
468

oharboe's avatar
oharboe committed
469
470
	if ((status = stm32x_erase_options(bank)) != ERROR_OK)
		return status;
zwelch's avatar
zwelch committed
471

oharboe's avatar
oharboe committed
472
473
474
475
	stm32x_info->option_bytes.protection[0] = prot_reg[0];
	stm32x_info->option_bytes.protection[1] = prot_reg[1];
	stm32x_info->option_bytes.protection[2] = prot_reg[2];
	stm32x_info->option_bytes.protection[3] = prot_reg[3];
zwelch's avatar
zwelch committed
476

oharboe's avatar
oharboe committed
477
478
479
	return stm32x_write_options(bank);
}

480
static int stm32x_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
oharboe's avatar
oharboe committed
481
482
483
{
	stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
	target_t *target = bank->target;
484
	uint32_t buffer_size = 16384;
oharboe's avatar
oharboe committed
485
	working_area_t *source;
486
	uint32_t address = bank->base + offset;
oharboe's avatar
oharboe committed
487
488
489
	reg_param_t reg_params[4];
	armv7m_algorithm_t armv7m_info;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
490

491
	uint8_t stm32x_flash_write_code[] = {
oharboe's avatar
oharboe committed
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
									/* write: */
		0xDF, 0xF8, 0x24, 0x40,		/* ldr	r4, STM32_FLASH_CR */
		0x09, 0x4D,					/* ldr	r5, STM32_FLASH_SR */
		0x4F, 0xF0, 0x01, 0x03,		/* mov	r3, #1 */
		0x23, 0x60,					/* str	r3, [r4, #0] */
		0x30, 0xF8, 0x02, 0x3B,		/* ldrh r3, [r0], #2 */
		0x21, 0xF8, 0x02, 0x3B,		/* strh r3, [r1], #2 */
									/* busy: */
		0x2B, 0x68,					/* ldr 	r3, [r5, #0] */
		0x13, 0xF0, 0x01, 0x0F,		/* tst 	r3, #0x01 */
		0xFB, 0xD0,					/* beq 	busy */
		0x13, 0xF0, 0x14, 0x0F,		/* tst	r3, #0x14 */
		0x01, 0xD1,					/* bne	exit */
		0x01, 0x3A,					/* subs	r2, r2, #1 */
		0xED, 0xD1,					/* bne	write */
									/* exit: */
508
		0xFE, 0xE7,					/* b exit */
oharboe's avatar
oharboe committed
509
510
511
		0x10, 0x20, 0x02, 0x40,		/* STM32_FLASH_CR:	.word 0x40022010 */
		0x0C, 0x20, 0x02, 0x40		/* STM32_FLASH_SR:	.word 0x4002200C */
	};
zwelch's avatar
zwelch committed
512

oharboe's avatar
oharboe committed
513
514
515
	/* flash write code */
	if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &stm32x_info->write_algorithm) != ERROR_OK)
	{
516
		LOG_WARNING("no working area available, can't do block memory writes");
oharboe's avatar
oharboe committed
517
518
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};
zwelch's avatar
zwelch committed
519

zwelch's avatar
zwelch committed
520
	if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code)) != ERROR_OK)
oharboe's avatar
   
oharboe committed
521
		return retval;
oharboe's avatar
oharboe committed
522
523
524
525
526
527
528
529
530
531

	/* memory buffer */
	while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
	{
		buffer_size /= 2;
		if (buffer_size <= 256)
		{
			/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
			if (stm32x_info->write_algorithm)
				target_free_working_area(target, stm32x_info->write_algorithm);
zwelch's avatar
zwelch committed
532

533
			LOG_WARNING("no large enough working area available, can't do block memory writes");
oharboe's avatar
oharboe committed
534
535
536
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	};
zwelch's avatar
zwelch committed
537

oharboe's avatar
oharboe committed
538
539
	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARMV7M_MODE_ANY;
zwelch's avatar
zwelch committed
540

oharboe's avatar
oharboe committed
541
542
543
544
	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
	init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
zwelch's avatar
zwelch committed
545

oharboe's avatar
oharboe committed
546
547
	while (count > 0)
	{
548
		uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
zwelch's avatar
zwelch committed
549

zwelch's avatar
zwelch committed
550
		if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer)) != ERROR_OK)
oharboe's avatar
   
oharboe committed
551
			break;
zwelch's avatar
zwelch committed
552

oharboe's avatar
oharboe committed
553
554
555
		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
zwelch's avatar
zwelch committed
556

zwelch's avatar
zwelch committed
557
		if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, stm32x_info->write_algorithm->address, \
oharboe's avatar
oharboe committed
558
559
				stm32x_info->write_algorithm->address + (sizeof(stm32x_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK)
		{
560
			LOG_ERROR("error executing stm32x flash write algorithm");
561
			retval = ERROR_FLASH_OPERATION_FAILED;
oharboe's avatar
oharboe committed
562
563
			break;
		}
zwelch's avatar
zwelch committed
564

565
		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
oharboe's avatar
oharboe committed
566
		{
567
			LOG_ERROR("flash memory not erased before writing");
568
			/* Clear but report errors */
zwelch's avatar
zwelch committed
569
			target_write_u32(target, STM32_FLASH_SR, FLASH_PGERR);
570
571
572
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}
zwelch's avatar
zwelch committed
573

574
575
576
		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
		{
			LOG_ERROR("flash memory write protected");
577
			/* Clear but report errors */
zwelch's avatar
zwelch committed
578
			target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR);
oharboe's avatar
oharboe committed
579
580
581
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}
zwelch's avatar
zwelch committed
582

oharboe's avatar
oharboe committed
583
584
585
586
		buffer += thisrun_count * 2;
		address += thisrun_count * 2;
		count -= thisrun_count;
	}
zwelch's avatar
zwelch committed
587

oharboe's avatar
oharboe committed
588
589
	target_free_working_area(target, source);
	target_free_working_area(target, stm32x_info->write_algorithm);
zwelch's avatar
zwelch committed
590

oharboe's avatar
oharboe committed
591
592
593
594
	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
	destroy_reg_param(&reg_params[3]);
zwelch's avatar
zwelch committed
595

oharboe's avatar
oharboe committed
596
597
598
	return retval;
}

599
static int stm32x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
oharboe's avatar
oharboe committed
600
601
{
	target_t *target = bank->target;
602
603
604
605
	uint32_t words_remaining = (count / 2);
	uint32_t bytes_remaining = (count & 0x00000001);
	uint32_t address = bank->base + offset;
	uint32_t bytes_written = 0;
606
	uint8_t status;
607
	int retval;
zwelch's avatar
zwelch committed
608

609
610
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
611
		LOG_ERROR("Target not halted");
612
613
614
		return ERROR_TARGET_NOT_HALTED;
	}

oharboe's avatar
oharboe committed
615
616
	if (offset & 0x1)
	{
duane's avatar
duane committed
617
		LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
oharboe's avatar
oharboe committed
618
619
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}
zwelch's avatar
zwelch committed
620

oharboe's avatar
oharboe committed
621
622
623
	/* unlock flash registers */
	target_write_u32(target, STM32_FLASH_KEYR, KEY1);
	target_write_u32(target, STM32_FLASH_KEYR, KEY2);
zwelch's avatar
zwelch committed
624

oharboe's avatar
oharboe committed
625
	/* multiple half words (2-byte) to be programmed? */
zwelch's avatar
zwelch committed
626
	if (words_remaining > 0)
oharboe's avatar
oharboe committed
627
628
629
630
631
632
633
	{
		/* try using a block write */
		if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
		{
			if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
			{
				/* if block write failed (no sufficient working area),
zwelch's avatar
zwelch committed
634
				 * we use normal (slow) single dword accesses */
635
				LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
oharboe's avatar
oharboe committed
636
637
638
			}
			else if (retval == ERROR_FLASH_OPERATION_FAILED)
			{
639
				LOG_ERROR("flash writing failed with error code: 0x%x", retval);
oharboe's avatar
oharboe committed
640
641
642
643
644
645
646
647
648
649
650
651
652
				return ERROR_FLASH_OPERATION_FAILED;
			}
		}
		else
		{
			buffer += words_remaining * 2;
			address += words_remaining * 2;
			words_remaining = 0;
		}
	}

	while (words_remaining > 0)
	{
zwelch's avatar
zwelch committed
653
654
		uint16_t value;
		memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
655

oharboe's avatar
oharboe committed
656
		target_write_u32(target, STM32_FLASH_CR, FLASH_PG);
657
		target_write_u16(target, address, value);
zwelch's avatar
zwelch committed
658

oharboe's avatar
oharboe committed
659
		status = stm32x_wait_status_busy(bank, 5);
zwelch's avatar
zwelch committed
660

zwelch's avatar
zwelch committed
661
		if ( status & FLASH_WRPRTERR )
662
663
		{
			LOG_ERROR("flash memory not erased before writing");
oharboe's avatar
oharboe committed
664
			return ERROR_FLASH_OPERATION_FAILED;
665
		}
zwelch's avatar
zwelch committed
666
		if ( status & FLASH_PGERR )
667
668
		{
			LOG_ERROR("flash memory write protected");
oharboe's avatar
oharboe committed
669
			return ERROR_FLASH_OPERATION_FAILED;
670
		}
oharboe's avatar
oharboe committed
671
672
673
674
675

		bytes_written += 2;
		words_remaining--;
		address += 2;
	}
zwelch's avatar
zwelch committed
676

oharboe's avatar
oharboe committed
677
678
	if (bytes_remaining)
	{
zwelch's avatar
zwelch committed
679
		uint16_t value = 0xffff;
680
681
		memcpy(&value, buffer + bytes_written, bytes_remaining);

oharboe's avatar
oharboe committed
682
		target_write_u32(target, STM32_FLASH_CR, FLASH_PG);
683
		target_write_u16(target, address, value);
zwelch's avatar
zwelch committed
684

oharboe's avatar
oharboe committed
685
		status = stm32x_wait_status_busy(bank, 5);
zwelch's avatar
zwelch committed
686

zwelch's avatar
zwelch committed
687
		if ( status & FLASH_WRPRTERR )
688
689
		{
			LOG_ERROR("flash memory not erased before writing");
oharboe's avatar
oharboe committed
690
			return ERROR_FLASH_OPERATION_FAILED;
691
		}
zwelch's avatar
zwelch committed
692
		if ( status & FLASH_PGERR )
693
694
		{
			LOG_ERROR("flash memory write protected");
oharboe's avatar
oharboe committed
695
			return ERROR_FLASH_OPERATION_FAILED;
696
		}
oharboe's avatar
oharboe committed
697
	}
zwelch's avatar
zwelch committed
698

oharboe's avatar
oharboe committed
699
	target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
zwelch's avatar
zwelch committed
700

oharboe's avatar
oharboe committed
701
702
703
	return ERROR_OK;
}

mifi's avatar
mifi committed
704
static int stm32x_probe(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
705
706
707
708
{
	target_t *target = bank->target;
	stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
	int i;
zwelch's avatar
zwelch committed
709
	uint16_t num_pages;
710
	uint32_t device_id;
711
	int page_size;
zwelch's avatar
zwelch committed
712

713
714
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
715
		LOG_ERROR("Target not halted");
716
717
718
		return ERROR_TARGET_NOT_HALTED;
	}

oharboe's avatar
oharboe committed
719
	stm32x_info->probed = 0;
zwelch's avatar
zwelch committed
720

oharboe's avatar
oharboe committed
721
722
	/* read stm32 device id register */
	target_read_u32(target, 0xE0042000, &device_id);
duane's avatar
duane committed
723
	LOG_INFO( "device id = 0x%08" PRIx32 "", device_id );
zwelch's avatar
zwelch committed
724

oharboe's avatar
oharboe committed
725
	/* get flash size from target */
726
	if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK)
727
	{
728
729
		/* failed reading flash size, default to max target family */
		num_pages = 0xffff;
730
	}
zwelch's avatar
zwelch committed
731

732
	if ((device_id & 0x7ff) == 0x410)
oharboe's avatar
oharboe committed
733
	{
734
735
736
737
		/* medium density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;
zwelch's avatar
zwelch committed
738

739
740
741
742
743
744
745
746
		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 128k flash" );
			num_pages = 128;
		}
	}
747
748
749
750
751
752
	else if ((device_id & 0x7ff) == 0x412)
	{
		/* low density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;
zwelch's avatar
zwelch committed
753

754
755
756
757
758
759
760
761
		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 32k flash" );
			num_pages = 32;
		}
	}
762
763
764
765
766
767
	else if ((device_id & 0x7ff) == 0x414)
	{
		/* high density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;
zwelch's avatar
zwelch committed
768

769
770
771
772
773
774
775
776
		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 512k flash" );
			num_pages = 512;
		}
	}
777
778
779
780
781
782
	else if ((device_id & 0x7ff) == 0x418)
	{
		/* connectivity line density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;
zwelch's avatar
zwelch committed
783

784
785
786
787
788
789
790
791
		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 256k flash" );
			num_pages = 256;
		}
	}
792
793
794
795
	else
	{
		LOG_WARNING( "Cannot identify target as a STM32 family." );
		return ERROR_FLASH_OPERATION_FAILED;
oharboe's avatar
oharboe committed
796
	}
zwelch's avatar
zwelch committed
797

798
	LOG_INFO( "flash size = %dkbytes", num_pages );
zwelch's avatar
zwelch committed
799

800
	/* calculate numbers of pages */
801
	num_pages /= (page_size / 1024);
zwelch's avatar
zwelch committed
802

oharboe's avatar
oharboe committed
803
	bank->base = 0x08000000;
804
805
806
	bank->size = (num_pages * page_size);
	bank->num_sectors = num_pages;
	bank->sectors = malloc(sizeof(flash_sector_t) * num_pages);
zwelch's avatar
zwelch committed
807

808
	for (i = 0; i < num_pages; i++)
oharboe's avatar
oharboe committed
809
	{
810
811
		bank->sectors[i].offset = i * page_size;
		bank->sectors[i].size = page_size;
oharboe's avatar
oharboe committed
812
813
814
		bank->sectors[i].is_erased = -1;
		bank->sectors[i].is_protected = 1;
	}
zwelch's avatar
zwelch committed
815

oharboe's avatar
oharboe committed
816
	stm32x_info->probed = 1;
zwelch's avatar
zwelch committed
817

oharboe's avatar
oharboe committed
818
819
820
	return ERROR_OK;
}

mifi's avatar
mifi committed
821
static int stm32x_auto_probe(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
822
823
824
825
826
827
828
{
	stm32x_flash_bank_t *stm32x_info = bank->driver_priv;
	if (stm32x_info->probed)
		return ERROR_OK;
	return stm32x_probe(bank);
}

mifi's avatar
mifi committed
829
830
#if 0
static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
oharboe's avatar
oharboe committed
831
832
833
{
	return ERROR_OK;
}
mifi's avatar
mifi committed
834
#endif
oharboe's avatar
oharboe committed
835